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
'source' 카테고리의 다른 글
노드 express js의 mysql 행을 동적으로 업데이트하는 방법 (0) | 2022.09.22 |
---|---|
숫자에 대한 Larabel 규칙 유효성 검사 (0) | 2022.09.22 |
Vue.js의 'data:'와 'data()'의 차이점은 무엇입니까? (0) | 2022.09.22 |
그라들 태스크 - Java 응용 프로그램에 인수를 전달합니다. (0) | 2022.09.22 |
문자열에서 숫자 추출 - StringUtils Java (0) | 2022.09.22 |