source

MySql에서 DATETIME 필드의 날짜 부분에 인덱스를 만드는 방법

factcode 2022. 9. 22. 00:08
반응형

MySql에서 DATETIME 필드의 날짜 부분에 인덱스를 만드는 방법

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' 

시간이 오래 걸린다.

편집:

"MySQL의 DATETIME을 피할있는 이유"에 대한 이 블로그 게시물을 참조하십시오.

내 기억이 맞다면, 당신은 함수를 통해 열을 전달하고 있기 때문에 테이블 전체를 스캔할 수 있습니다.Query Optimizer가 함수의 결과를 제대로 알 수 없기 때문에 인덱스를 바이패스하여 각 열에 대해 함수를 고분고분하게 실행합니다.

제가 할 일은 다음과 같습니다.

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

그럼 2008년 8월 17일에 있었던 모든 일을 알 수 있을 겁니다.

귀엽게 말하는 것은 아니지만, 간단한 방법은 날짜 부분과 색인만 기재한 새로운 열을 추가하는 것입니다.

다른 옵션(버전 5.7.3 이상과 관련)은 datetime 컬럼에 따라 생성된/가상 컬럼을 작성한 후 인덱스를 작성하는 것입니다.

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

날짜 부분에만 색인을 만들 수 없습니다.꼭 그래야 하는 이유가 있나요?

날짜 부분에만 인덱스를 생성할 수 있더라도 옵티마이저는 위의 쿼리에 인덱스를 사용하지 않을 수 있습니다.

찾을 수 있을 것 같아

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

효율적이며 원하는 대로 할 수 있습니다.

mySql의 자세한 내용은 모르겠지만 날짜 필드 전체를 인덱싱하는 것이 나쁠 것은 없습니다.

검색만 하면 됩니다.

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

인덱스가 b-tree이거나 다른 합리적인 것이라면 빠르게 찾을 수 있을 것입니다.

MySQL 사이트에서 이 문제에 대한 기능 요청에 대해 Valeri Kravchuk이 이 방법을 사용한다고 합니다.

"그동안 DATETIME 값을 문자열로 저장하기 위해 문자 열을 사용할 수 있습니다. 처음 N자만 인덱싱됩니다.MySQL 5에서 트리거를 주의 깊게 사용하면 이 아이디어를 바탕으로 상당히 견고한 솔루션을 만들 수 있습니다."

이 열을 추가하는 루틴을 쉽게 작성한 다음 트리거를 사용하여 이 열을 동기화할 수 있습니다.이 문자열 열의 색인은 매우 빠릅니다.

가장 효과적인 해결책 중 하나는 날짜 시간이 아닌 시간 스탬프를 사용하는 것입니다.INT로 저장되며 충분히 인덱싱됩니다.개인적으로는 트랜잭션 테이블에서 약 100만 개의 레코드가 있고 속도가 느려지는 문제가 발생했는데, 마지막으로 인덱스필드의 불량(datetime)이 원인이라고 지적했습니다.이제 매우 빠르게 작동합니다.

mySQL의 자세한 내용은 모르겠지만 날짜 필드 전체를 인덱싱하는 것이 나쁠 것은 없습니다.

* 트리, 해시 등에 함수 마법을 사용하면 값을 얻으려면 함수를 호출해야 하기 때문에 사라집니다.그러나 미리 결과를 알 수 없기 때문에 표의 전체 스캔을 수행해야 합니다.

추가할 것이 없습니다.

계산된(계산된) 인덱스 같은 걸 말하는 건가?하지만 지금까지 인터시스템즈 카체에서만 볼 수 있었습니다.관계형 데이터베이스(AFAIK)에는 없는 것 같습니다.

좋은 해결책은 다음과 같습니다(업데이트된 clintp 예).

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

" " " 를 00:00:00.0000 ★★★★★★★★★★★★★★★★★」00:00제 의견으로는 별 차이가 없습니다(일반적으로 이 형식으로 사용해 왔습니다).

datetime LIKE something%도 인덱스를 잡지 않습니다.

WHERE datetime_field > = curdate()를 사용합니다.
수 .
오늘 대상 : 00:00:00 ~ 오늘 : 23 : 59 : 59 : 59

'date'는 무엇을 의미합니까? (DEPLY SELECT * FROM 트랜잭션 목록에서 date(TranDateTime) = '2008-08-17'을 실행합니다.)

date() 함수 때문에 인덱스를 사용하지 않는 경우 범위 쿼리는 빠르게 실행됩니다.

TranDateTime > = '2008-08-17' 및 TranDateTime <2008-08-18> 트랜잭션 목록에서 선택

함수(mysql에서도 가능한 경우)를 기반으로 인덱스를 작성하는 대신 where 구를 사용하여 범위를 비교합니다.예를 들어 다음과 같습니다.

여기서 TranDateTime > '2008-08-17 00:00:00' 및 TranDateTime < '2008-08-17 11:59:59')

이를 통해 DB는 TranDateTime의 인덱스를 사용하여 선택을 수행할 수 있습니다.

표를 수정하거나 새 표를 작성하는 경우, 날짜 및 시간을 각 유형의 개별 열에 저장하는 것이 좋습니다.날짜/시간에서 파생된 날짜 전용 열에 비해 훨씬 작은 키 공간과 축소된 스토리지를 통해 성능을 얻을 수 있습니다.이를 통해 다른 열보다 먼저 복합 키에서 사용할 수도 있습니다.

OP의 경우:

+-------------------+------------------+------+-----+---------+----------------+
| 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       |                |
| TranDate          | date             | NO   |     | NULL    |                |
| TranTime          | time             | NO   |     | NULL    |                |
| Amount            | double           | YES  |     | 0       |                |
| Action            | smallint(6)      | YES  |     | 0       |                |
| Uid               | int(11)          | YES  |     | 1       |                |
| AuthId            | int(11)          | YES  |     | 1       |                |
+-------------------+------------------+------+-----+---------+----------------+

만 하여 새 .convert(datetime, left(date_field,10))이치노

언급URL : https://stackoverflow.com/questions/95183/how-does-one-create-an-index-on-the-date-part-of-datetime-field-in-mysql

반응형