문제

MySQL에는 파일에 대한 정보가 포함 된 매우 큰 테이블 (~ 100million 레코드)이 있습니다. 정보 중 하나는 각 파일의 수정 날짜입니다.

지정된 날짜 범위에 맞는 파일 수를 계산하는 쿼리를 작성해야합니다. 그렇게하기 위해 나는 이러한 범위를 지정하는 작은 테이블을 만들었고 (모든 날) : 다음과 같이 보입니다.

DateRanges
range_id   range_name   range_start   range_end
1          0-90         0             90
2          91-180       91            180
3          181-365      181           365
4          366-1095     366           1095
5          1096+        1096          999999999

다음과 같이 보이는 쿼리를 썼습니다.

SELECT r.range_name, sum(IF((DATEDIFF(CURDATE(),t.file_last_access) > r.range_start and DATEDIFF(CURDATE(),t.file_last_access) < r.range_end),1,0)) as FileCount
FROM `DateRanges` r, `HugeFileTable` t
GROUP BY r.range_name

그러나 예상 대로이 쿼리는 영원히 실행됩니다. 나는 그것이 MySQL에 각 파일에서 datediff () 계산을 수행 할 때마다 MySQL에 5 번 거대한 5 번을 겪기 때문이라고 생각합니다.

내가 대신하고 싶은 것은 거대한 필수 레코드를 한 번만 레코드로 만 거리는 것입니다. 각 파일에 대해 적절한 범위 _name 총액에서 카운트를 증가시킵니다. 어떻게하는지 알 수 없습니다 ....

누구든지 이것을 도울 수 있습니까?

감사.

편집하다: MySQL 버전 : 5.0.45, 테이블은 Myisam입니다

edit2: 다음은 의견에 요청 된 descibe입니다.

id  select_type  table  type  possible_keys  key  key_len  ref  rows      Extra  
1   SIMPLE       r      ALL   NULL           NULL NULL     NULL 5         Using temporary; Using filesort 
1   SIMPLE       t      ALL   NULL           NULL NULL     NULL 96506321   
도움이 되었습니까?

해결책

먼저 색인을 만듭니다 HugeFileTable.file_last_access.

그런 다음 다음 쿼리를 시도하십시오.

SELECT r.range_name, COUNT(t.file_last_access) as FileCount
FROM `DateRanges` r
 JOIN `HugeFileTable` t 
 ON (t.file_last_access BETWEEN 
   CURDATE() + INTERVAL r.range_start DAY AND 
   CURDATE() + INTERVAL r.range_end DAY)
GROUP BY r.range_name;

여기에 있습니다 EXPLAIN MySQL 5.0.75 에서이 쿼리를 시도했을 때 얻은 계획 (Brevity를 위해 편집) :

+-------+-------+------------------+----------------------------------------------+
| table | type  | key              | Extra                                        |
+-------+-------+------------------+----------------------------------------------+
| t     | index | file_last_access | Using index; Using temporary; Using filesort | 
| r     | ALL   | NULL             | Using where                                  | 
+-------+-------+------------------+----------------------------------------------+

여전히 잘 작동하지 않을 것입니다. 사용하여 GROUP BY, 쿼리는 임시 테이블이 발생하여 비쌀 수 있습니다. 당신이 그것에 대해 할 수있는 일은 많지 않습니다.

그러나 적어도이 쿼리는 원래 쿼리에있는 데카르트 제품을 제거합니다.


업데이트: 다음은 상관 관계 서브 쿼리를 사용하지만 GROUP BY.

SELECT r.range_name,
  (SELECT COUNT(*) 
   FROM `HugeFileTable` t 
   WHERE t.file_last_access BETWEEN 
     CURDATE() - INTERVAL r.range_end DAY AND 
     CURDATE() - INTERVAL r.range_start DAY
  ) as FileCount
FROM `DateRanges` r;

그만큼 EXPLAIN 계획은 임시 테이블이나 파일 조트를 보여주지 않습니다 (적어도 테스트 테이블에있는 사소한 행의 행으로) :

+----+--------------------+-------+-------+------------------+--------------------------+
| id | select_type        | table | type  | key              | Extra                    |
+----+--------------------+-------+-------+------------------+--------------------------+
|  1 | PRIMARY            | r     | ALL   | NULL             |                          | 
|  2 | DEPENDENT SUBQUERY | t     | index | file_last_access | Using where; Using index | 
+----+--------------------+-------+-------+------------------+--------------------------+

데이터 세트 에서이 쿼리를 시도하고 더 나은 성능이 있는지 확인하십시오.

다른 팁

글쎄, 그것을 시작하십시오 file_last_access 이다 인덱스 테이블을 위해 HugeFileTable.

이것이 가능하는지 확실하지 않지만 날짜 제한을 먼저 계산하려고 노력하십시오 (날짜부터 파일 지금까지 ), 그런 다음> = 및 <=로 일부 쿼리를 사용하십시오. 이론적으로 적어도 성능을 향상시킬 것입니다.

비교는 다음과 같습니다.

 t.file_last_access >= StartDate AND t.file_last_access <= EndDate 

Curdate ()를 제거하고 SQL에서 각 행에 대해이 기능을 두 번 실행하므로 쿼리에 날짜를두면 약간의 개선을 얻을 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top