programing

MySQL이 밀리초/마이크로초 정밀도를 지원하지 않는 이유는 무엇입니까?

padding 2023. 8. 11. 21:35
반응형

MySQL이 밀리초/마이크로초 정밀도를 지원하지 않는 이유는 무엇입니까?

그래서 저는 MySQL에서 가장 짜증나는 버그를 발견했습니다.

보하니그아그▁apparent니.TIMESTAMP필드 및 지원 기능은 초 이상의 정밀도를 지원하지 않습니다!?

독트린을 , 저는 그 꼭 는 와저서는 PHP독트저있고고, 저그마가초다니정필요합말다있로니습크사고는는이하그용그래것을하용사을린저seconds▁the▁so▁(i▁micro▁those다있(니▁using▁need,습▁doctrine▁i다▁really▁am는그▁php고사니▁and하▁and▁i용).actAs: [Timestampable]재산).

용▁a▁다▁use▁i니▁can▁a았▁i습을 사용할 수 있는 a를 찾았습니다.BIGINT필드에 값을 저장합니다.하지만 교리가 밀리초를 추가할까요?그냥 NOW()를 현장에 배정하는 것 같습니다.코드에 뿌려진 날짜 조작 기능(SQL)이 깨질까 봐 걱정도 됩니다.

저는 또한 UDF 확장을 컴파일하는 것에 관한 것을 보았습니다.이것은 저나 미래의 유지관리자가 업그레이드하고 똥을 누기 때문에 허용되지 않습니다.

적절한 해결책을 찾은 사람이 있습니까?

다음 독자를 위한 정보를 위해 버전 5.6.4에서 이 버그가 마침내 수정되었습니다.

"MySQL은 이제 최대 마이크로초의 정밀도로 TIME, DATTIME 및 TIME 값에 대해 분수초를 지원합니다."

SQL92-Standard에서:

  • 타임스탬프 - 날짜/시간 필드의 년, 월, 일, 시간, 분 및 초를 포함합니다.

SQL92 호환 데이터베이스는 제 관점에서 밀리초 또는 마이크로초를 지원할 필요가 없습니다.따라서 버그 #8523은 "기능 요청"으로 올바르게 표시됩니다.

독트린은 마이크로초 등을 어떻게 처리합니까?방금 다음을 찾았습니다.독트린#타임스탬프:

타임스탬프 데이터 유형은 날짜와 시간 데이터 유형의 단순한 조합입니다.타임스탬프 유형의 값은 날짜 및 시간 문자열 값을 공백으로 연결된 단일 문자열에 결합하여 표시합니다.따라서 형식 템플릿은 YYYY-MM-DDHH:MI:SS.

따라서 SQL92-docs에서와 같이 마이크로초도 언급되지 않았습니다.하지만 저는 교리를 깊이 파고들지는 않지만, 예를 들어 자바의 동면과 같은 ORM인 것 같습니다.따라서 BIGINT 또는 STRING에 시간 정보를 저장할 수 있고 PHP 클래스에 해당 정보를 읽고 쓸 책임이 있는 모델을 직접 정의할 수 있습니다.

BTW: 가까운 미래에 MySQL이 밀리초/마이크로초의 타임스탬프를 지원하지 않을 것으로 예상합니다(예: 향후 5년).

해결책을 찾았어요!이것은 매우 깨끗하고 응용 프로그램 코드를 변경할 필요가 없습니다.이것은 독트린에 효과가 있으며 다른 ORM에도 적용될 수 있습니다.

기본적으로 타임스탬프를 문자열로 저장합니다.

날짜 문자열의 형식이 올바르면 비교 및 정렬이 작동합니다.MySQL 시간 함수는 날짜 문자열을 전달할 때 마이크로초 부분을 잘라냅니다.마이크로초의 정밀도가 필요하지 않은 경우에도 괜찮습니다.date_diff

SELECT DATEDIFF('2010-04-04 17:24:42.000000','2010-04-04 17:24:42.999999');
> 0

SELECT microsecond('2010-04-04 17:24:42.021343');
> 21343 

나는 결국 글을 썼습니다.MicroTimestampable이것을 구현할 클래스.필드에 다음과 같이 주석을 달 뿐입니다.actAs:MicroTimestampable그리고 voila, MySQL 및 Doctrine을 사용한 마이크로타임 정밀도.

교리_템플릿_MicroTimes 스탬프 테이블

class Doctrine_Template_MicroTimestampable extends Doctrine_Template_Timestampable
{
    /**
     * Array of Timestampable options
     *
     * @var string
     */
    protected $_options = array('created' =>  array('name'          =>  'created_at',
                                                    'alias'         =>  null,
                                                    'type'          =>  'string(30)',
                                                    'format'        =>  'Y-m-d H:i:s',
                                                    'disabled'      =>  false,
                                                    'expression'    =>  false,
                                                    'options'       =>  array('notnull' => true)),
                                'updated' =>  array('name'          =>  'updated_at',
                                                    'alias'         =>  null,
                                                    'type'          =>  'string(30)',
                                                    'format'        =>  'Y-m-d H:i:s',
                                                    'disabled'      =>  false,
                                                    'expression'    =>  false,
                                                    'onInsert'      =>  true,
                                                    'options'       =>  array('notnull' => true)));

    /**
     * Set table definition for Timestampable behavior
     *
     * @return void
     */
    public function setTableDefinition()
    {
        if ( ! $this->_options['created']['disabled']) {
            $name = $this->_options['created']['name'];
            if ($this->_options['created']['alias']) {
                $name .= ' as ' . $this->_options['created']['alias'];
            }
            $this->hasColumn($name, $this->_options['created']['type'], null, $this->_options['created']['options']);
        }

        if ( ! $this->_options['updated']['disabled']) {
            $name = $this->_options['updated']['name'];
            if ($this->_options['updated']['alias']) {
                $name .= ' as ' . $this->_options['updated']['alias'];
            }
            $this->hasColumn($name, $this->_options['updated']['type'], null, $this->_options['updated']['options']);
        }

        $this->addListener(new Doctrine_Template_Listener_MicroTimestampable($this->_options));
    }
}

교리_템플릿_수신기_마이크로타임스탬프 가능

class Doctrine_Template_Listener_MicroTimestampable extends Doctrine_Template_Listener_Timestampable
{
    protected $_options = array();

    /**
     * __construct
     *
     * @param string $options 
     * @return void
     */
    public function __construct(array $options)
    {
        $this->_options = $options;
    }

    /**
     * Gets the timestamp in the correct format based on the way the behavior is configured
     *
     * @param string $type 
     * @return void
     */
    public function getTimestamp($type, $conn = null)
    {
        $options = $this->_options[$type];

        if ($options['expression'] !== false && is_string($options['expression'])) {
            return new Doctrine_Expression($options['expression'], $conn);
        } else {
            if ($options['type'] == 'date') {
                return date($options['format'], time().".".microtime());
            } else if ($options['type'] == 'timestamp') {
                return date($options['format'], time().".".microtime());
            } else {
                return time().".".microtime();
            }
        }
    }
}

Dutrin을 사용하여 데이터를 저장하고 Dutrin도 분수 초를 지원하지 않기 때문에 병목 현상은 MySQL이 아닙니다.

더 필요한 하고 그 합니다.microtime()두 개의 서로 다른 필드, 즉 에포크 초 타임스탬프용 필드와 마이크로초 부분에 저장할 수 있습니다. 표준 수 SQL을 정렬하고 수 있습니다.

네이티브 타임스탬프 유형 대신 epoch 초를 저장하는 것이 일반적으로 더 쉽고 네이티브 타임스탬프 유형과 국제적으로 서비스를 제공하는 전체 시간대 문제를 피할 수 있기 때문에 권장합니다.

Mysql 버전 5.6.4부터는 마이크로초를 열에 저장합니다.

"MySQL은 이제 최대 마이크로초의 정밀도로 TIME, DATTIME 및 TIME 값에 대해 분수초를 지원합니다."

예:

CREATE TABLE `test_table` (
`name` VARCHAR(1000) ,
`orderdate` DATETIME(6)
);

INSERT INTO test_table VALUES('A','2010-12-10 14:12:09.019473');

SELECT * FROM test_table;

데이터 유형을 datetime으로 변경하기만 하면 됩니다(6).

자세한 내용은 다음을 참조하십시오. http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds.html

시간(밀리초)에 대한 또 다른 해결 방법입니다.함수 "time_in_msec"이(가) 생성되었습니다.

용도:

두 날짜 간의 차이(밀리초)입니다.

mysql> SELECT time_in_msec('2010-07-12 23:14:36.233','2010-07-11 23:04:00.000') AS miliseconds;
+-------------+
| miliseconds |
+-------------+
| 87036233    |
+-------------+
1 row in set, 2 warnings (0.00 sec)



DELIMITER $$

DROP FUNCTION IF EXISTS `time_in_msec`$$

CREATE FUNCTION `time_in_msec`(ftime VARCHAR(23),stime VARCHAR(23)) RETURNS VARCHAR(30) CHARSET latin1
BEGIN
    DECLARE msec INT DEFAULT 0;
    DECLARE sftime,sstime VARCHAR(27);
    SET ftime=CONCAT(ftime,'000');
    SET stime=CONCAT(stime,'000');
    SET  msec=TIME_TO_SEC(TIMEDIFF(ftime,stime))*1000+TRUNCATE(MICROSECOND(TIMEDIFF(ftime,stime))/1000,0);
    RETURN msec;
END$$

DELIMITER ;

이제 마이크로초를 사용할 수 있습니다.

mysql> select @@version;
+-----------+
| @@version |
+-----------+
| 5.6.26    |
+-----------+
1 row in set (0.00 sec)

mysql> select now(6);
+----------------------------+
| now(6)                     |
+----------------------------+
| 2016-01-16 21:18:35.496021 |
+----------------------------+
1 row in set (0.00 sec)

언급했듯이 마이크로초 지원은 버전 5.6.4에서 추가되었습니다.

다음은 몇 초 동안 사용할 수 있습니다.

drop procedure if exists doSomething123;
delimiter $$
create procedure doSomething123()
begin
    DECLARE dtBEGIN,dtEnd DATETIME(6);
    DECLARE theCount,slp INT;
    set dtBegin=now(6); -- see http://dev.mysql.com/doc/refman/5.7/en/fractional-seconds.html

    -- now do something to profile
    select count(*) into theCount from questions_java where closeDate is null;
    select sleep(2) into slp;
    -- not the above but "something"

    set dtEnd=now(6); -- see http://dev.mysql.com/doc/refman/5.7/en/fractional-seconds.html
    select timediff(dtEnd,dtBegin) as timeDiff,timediff(dtEnd,dtBegin)+MICROSECOND(timediff(dtEnd,dtBegin))/1000000 seconds;
    -- select dtEnd,dtBegin;
end$$
delimiter ;

테스트:

call doSomething123();
+-----------------+----------+
| timeDiff        | seconds  |
+-----------------+----------+
| 00:00:02.008378 | 2.016756 |
+-----------------+----------+

그것에 대한 또 다른 관점:

set @dt1=cast('2016-01-01 01:00:00.1111' as datetime(6)); 
set @dt2=cast('2016-01-01 01:00:00.8888' as datetime(6)); 

select @dt1,@dt2,MICROSECOND(timediff(@dt2,@dt1))/1000000 micros;
+----------------------------+----------------------------+--------+
| @dt1                       | @dt2                       | micros |
+----------------------------+----------------------------+--------+
| 2016-01-01 01:00:00.111100 | 2016-01-01 01:00:00.888800 | 0.7777 |
+----------------------------+----------------------------+--------+

시간 값의 분수 초라는 제목의 MySQL 매뉴얼 페이지 참조

언급URL : https://stackoverflow.com/questions/2572209/why-doesnt-mysql-support-millisecond-microsecond-precision

반응형