2008-09-18 4 views
57

DATETIME 필드의 날짜 부분에 인덱스를 만들려면 어떻게해야합니까?MySQL의 DATETIME 필드의 날짜 부분에 인덱스를 만드는 방법

mysql> SHOW COLUMNS FROM transactionlist; 
+-------------------+------------------+------+-----+---------+----------------+ 
| Field    | Type    | Null | Key | Default | Extra   | 
+-------------------+------------------+------+-----+---------+----------------+ 
| TransactionNumber | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| WagerId   | int(11)   | YES | MUL | 0  |    | 
| TranNum   | int(11)   | YES | MUL | 0  |    | 
| TranDateTime  | datetime   | NO |  | NULL |    | 
| Amount   | double   | YES |  | 0  |    | 
| Action   | smallint(6)  | YES |  | 0  |    | 
| Uid    | int(11)   | YES |  | 1  |    | 
| AuthId   | int(11)   | YES |  | 1  |    | 
+-------------------+------------------+------+-----+---------+----------------+ 
8 rows in set (0.00 sec) 

TranDateTime은 내 표는 1,000,000 그것에 기록과 문이

SELECT * FROM transactionlist where date(TranDateTime) = '2008-08-17' 

시간이 오래 걸립니다 발생으로 트랜잭션의 날짜와 시간을 저장하는 데 사용됩니다.

편집 :

는 " Why MySQL’s DATETIME can and should be avoided"

+3

당신이 한 가지 제안 해 준 링크에 대한 경고문 :이 게시물은 유치함에 거의 접해있는 그런 흥분과 분노로 작성되었습니다. 그리고 작가는 비평을 뒤로 치지 않고 여전히 그가 말한 것을지지한다고 언급하면서도 그의 주장은 각자 날씬 해지고있다. 댓글을 읽는다면 여전히 시간 낭비가 아닙니다. – kommradHomer

답변

50

올바르게 기억하면 함수를 통해 열을 전달하기 때문에 전체 테이블 스캔이 실행됩니다. MySQL은 쿼리 최적화 프로그램이 실제로 함수의 결과를 알 수 없기 때문에 인덱스를 우회하여 각 열에 대해 함수를 순조롭게 실행할 것입니다. 당신에게 정확하게 2008-08-18 0시 0분 0초에서 일어난 2011-04-18에 일어난 모든 것을, 모든 것을 제공해야

SELECT * FROM transactionlist 
WHERE TranDateTime BETWEEN '2008-08-17 00:00:00' AND '2008-08-18 23:59:59'; 

:

는 내가 뭘 할 것은 같은입니다. 그게 문제라면, 두 번째 용어를 '2008-08-17 23:59:59'로 변경하면 2008-08-17 만 얻을 수 있습니다.

+0

정말 효과적입니다 ... – Arfeen

+1

나는이 사용법을 'YYYY-MM-DD 00:00:00'의 단축키로 생각했습니다. – kommradHomer

+3

저는 이것이 오래된 대답 인 것을 알고 있습니다. 그러나 나는 강요한다고 생각합니다. MySQL은 'DATETIME'에 문자열 비교를 사용하기 때문에; 귀하의 질의는 올바른 결과를 반환하고'TranDateTime = 2008-08-18 00 : 00 : 00' 행을 포함하지 않습니다. – Arth

0

가 무슨 말을 '설명'않습니다에이 블로그 게시물에서보세요?

이 때문에 날짜() 함수의 색인을 사용하지 않는 것 경우

, 범위 쿼리를 빠르게 실행해야합니다 (날짜 (TranDateTime) = '2011-04-18'는 어디 transactionlist로부터 SELECT *를 EXPLAIN 실행) :

SELECT * FROM transactionlist where TranDateTime> = '2008-08-17'AND TranDateTime < '2008-08-18'

+1

date()를 사용하면 인덱스를 치지 않습니다. MySQL은 같은 함수 호출 내에서 인덱스를 사용할 수 없습니다. – JBB

3

mySql의 특성에 대해서는 잘 모릅니다 만 날짜 필드를 인덱싱 할 때의 해악은 무엇입니까 전체적으로?

은 그럼 그냥 검색 :

select * from translist 
    where TranDateTime > '2008-08-16 23:59:59' 
     and TranDateTime < '2008-08-18 00:00:00' 

를 인덱스가 다른 즉, 이러한 신속 합리적인 발견을하셔야합니다 것 B-나무 또는 무언가가 있다면.

9

나는 귀여운 것처럼 들리는 것은 아니지만 간단한 방법은 날짜 부분과 색인 만 포함하는 새 열을 추가하는 것입니다.

+0

Yup - 시간 부분 만있는 열을 추가하고 DATETIME을 모두 제거하십시오. – JBB

+0

내 현재 솔루션은 'date'라는 또 다른 필드 호출을 추가하고 TranDateTime을 업데이트하면 날짜도 업데이트됩니다. 지금은 '날짜'에 대한 색인을 가지고 있으며 쿼리가 훨씬 빠릅니다. 내 테이블 크기가 + -5 % 증가했습니다 –

0

함수를 기반으로 색인을 만드는 것 (mysql에서도 가능하다면)은 where 절을 범위 비교로 만드십시오. 뭔가 같은 :

TranDateTime이> '2011-04-18 0시 0분 0초'와 TranDateTime < '2011-04-18 11시 59분 59초')가

이 있습니다 경우 DB는 TranDateTime에 인덱스를 사용합니다 (하나는 오른쪽에 있습니까?).

2

MySQL 사이트에서 바로이 문제에 대한 기능 요청에 대해 Valeriy Kravchuk이이 방법을 사용한다고 말했습니다.

"DATETIME 값을 문자열로 저장할 수 있으며 처음 N 문자 만 인덱싱됩니다 .5 MySQL에서 트리거를주의 깊게 사용하면이 아이디어를 기반으로 합리적인 솔루션을 만들 수 있습니다."

이 열을 쉽게 추가하고 트리거를 사용하면이 열을 계속 동기화 할 수 있습니다. 이 문자열 열의 색인은 매우 빨리 작성되어야합니다.

8

날짜 부분에만 색인을 만들 수 없습니다. 네가해야할 이유가 있니?

날짜 부분에만 색인을 만들 수있는 경우에도 옵티마이 저는 위의 쿼리에 대해 색인을 사용하지 않을 수 있습니다.

난 당신이

SELECT * FROM transactionlist WHERE TranDateTime BETWEEN '2008-08-17' AND '2008-08-18' 

이 효율적인가요 당신이 원하는 것을 찾을 수 있습니다 생각합니다.

0

mySQL의 특성에 대해서는 잘 모릅니다 만, 날짜 필드 전체를 인덱싱하는 데 어떤 해가됩니까?

값을 얻기 위해 함수를 호출해야하기 때문에 * trees, hashes, ...에 대한 기능 마법을 사용하는 경우. 그러나 결과를 미리 알지 못하기 때문에 테이블을 완전히 검사해야합니다.

추가 할 내용이 없습니다.

아마 계산 된 (계산 된) 인덱스와 같은 것을 의미 할 수도 있습니다. 그러나 지금까지는 Intersystems Caché에서만이 것을 보았습니다. 관계형 데이터베이스 (AFAIK)에 사례가 있다고 생각하지 않습니다.

좋은 솔루션은, 내 의견으로는, 다음 (업데이트 clintp 예)입니다 : 당신이 내 의견에 00:00:00.0000 또는 00:00는 차이가 없습니다 사용 여부

SELECT * FROM translist 
WHERE TranDateTime >= '2008-08-17 00:00:00.0000' 
    AND TranDateTime < '2008-08-18 00:00:00.0000' 

(나는 일반적으로이 형식으로 사용했습니다).

0

날짜가 convert(datetime, left(date_field,10)) 인 새 필드를 만든 다음 해당 필드의 색인을 생성하십시오.

1

꽤 좋은 작업 중 하나 인 좋은 해결책은 datetime 대신 timestamp를 시간으로 사용하는 것입니다. INT로 저장되어 충분히 색인이 생성됩니다. 개인적으로 나는 트랜잭션 테이블에서 이러한 문제를 겪었습니다.이 레코드는 약 백만 건의 레코드를 가지고 있으며 열심히 속도를 늦추면서 마침내 잘못된 인덱스 필드 (datetime)로 인해 발생했다고 지적했습니다. 이제 매우 빠르게 실행됩니다.

-2

누구가 좋아하는 것을 사용하지 않는 이유는 무엇입니까? 그것도 그 일을하지 않습니까? 그것은 그 어느 때보 다 빠르지 않을까요?

SELECT * FROM transactionlist where TranDateTime LIKE '2008-08-17%' 
1

datetime LIKE 뭔가 %가 색인을 catch하지 않습니다.

다음을 사용하십시오 : WHERE datetime_field> = curdate(); 인덱스를 잡을
,
커버 오늘 : 00 : 00 : 00이 지금까지 : 23 : 59 : 59
짓.

5

다른 옵션 (7.5.3 이상과 관련 있음)은 datetime 열을 기반으로 생성/가상 열을 만든 다음 인덱싱합니다.

CREATE TABLE `table` (
`my_datetime` datetime NOT NULL, 
`my_date` varchar(12) GENERATED ALWAYS AS (DATE(`my_daetime`)) STORED, 
KEY `my_idx` (`my_date`) 
) ENGINE=InnoDB; 
+0

왜 저장되고 가상은 아닌가요? – 0x13a

+0

색인을 생성하려면 저장해야합니다. 색인이 없으면 가상으로 표시 될 수 있습니다. –

+0

thx, 상상해 봅니다.이 기사와 혼동스러워합니다. https://www.percona.com/blog/2016/03/04/virtual -columns-in-mysql-and-mariadb/ – 0x13a

관련 문제