2015-01-23 2 views
0

를 추가 할 때이 내가 최적화하기 위해 노력하고있는 쿼리입니다. (. 논리합없이 backend_ubqstatweek_of_year = 2) 일주일 만의 동일한 검색어 : 느린 MySQL의 쿼리는 OR 문

SELECT SUM(`backend_ubqstat`.`complementary_revenue`) AS `complementary_revenue__sum`, SUM(`backend_ubqstat`.`revenue`) AS `revenue__sum` FROM `backend_ubqstat` 
INNER JOIN `backend_ubq` ON (`backend_ubqstat`.`ubq_id` = `backend_ubq`.`id`) 
WHERE 
(`backend_ubqstat`.`store_number` = 389 AND (`backend_ubqstat`.`week_of_year` = 2) 
AND (`backend_ubq`.`department` = 'QUINCAILLERIE' OR `backend_ubq`.`department` = 'OUTILLAGE') 
AND (`backend_ubq`.`sub_department` = 'Outillage à moteur' OR `backend_ubq`.`sub_department` = 'Outillage à main' OR `backend_ubq`.`sub_department` = 'Outil d\'assemblage')); 

실행할 0.1 초 걸린다. 첫 번째 쿼리의 주요 문제가 무엇인지 이해하려고합니다.

이 쿼리는 특정 상점에서 일주일에 걸친 일부 제품의 수익 합계를 계산합니다.

여러 주 (첫 번째 쿼리) :

+----+-------------+-----------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+------------------------------------+------+------------------------------------+ 
| id | select_type | table   | type | possible_keys                                           | key            | key_len | ref        | rows | Extra        | 
+----+-------------+-----------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+------------------------------------+------+------------------------------------+ 
| 1 | SIMPLE  | backend_ubqstat | range | backend_ubq_store_number_4ba08aefde7a0fdc_uniq,backend_ubq_ubq_id_2883f2962b976ce1_uniq,backend_ubq_week_of_year_534972be244e06dd_uniq,backend_ubqstat_week_of_year_1f3b84a6cf9999f7_idx | backend_ubqstat_week_of_year_1f3b84a6cf9999f7_idx | 4  | NULL        | 2975 | Using index condition; Using where | 
| 1 | SIMPLE  | backend_ubq  | eq_ref | PRIMARY,backend_ubq_department_2cef48a6c5825cef_uniq,backend_ubq_sub_department_65793aef847267e8_uniq,backend_ubq_department_2ebadbdc749719ff_idx          | PRIMARY           | 4  | xxxxxxxxxxx.backend_ubqstat.ubq_id | 1 | Using where      | 
+----+-------------+-----------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+------------------------------------+------+------------------------------------+ 

일주일 만 (두 번째 쿼리) : 이들은입니다

+----+-------------+-----------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+------------------------------------+------+-------------+ 
| id | select_type | table   | type | possible_keys                                           | key            | key_len | ref        | rows | Extra  | 
+----+-------------+-----------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+------------------------------------+------+-------------+ 
| 1 | SIMPLE  | backend_ubqstat | ref | backend_ubq_store_number_4ba08aefde7a0fdc_uniq,backend_ubq_ubq_id_2883f2962b976ce1_uniq,backend_ubq_week_of_year_534972be244e06dd_uniq,backend_ubqstat_week_of_year_1f3b84a6cf9999f7_idx | backend_ubqstat_week_of_year_1f3b84a6cf9999f7_idx | 4  | const,const      | 1475 | Using where | 
| 1 | SIMPLE  | backend_ubq  | eq_ref | PRIMARY,backend_ubq_department_2cef48a6c5825cef_uniq,backend_ubq_sub_department_65793aef847267e8_uniq,backend_ubq_department_2ebadbdc749719ff_idx          | PRIMARY           | 4  | xxxxxxxxx.backend_ubqstat.ubq_id | 1 | Using where | 
+----+-------------+-----------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+------------------------------------+------+-------------+ 

나는 논문의 결과를 모두 쿼리에 EXPLAIN 실행 두 테이블의 스키마 : 제품 표 : mysql> describe backend_ubq;

+----------------+----------------------+------+-----+---------+----------------+ 
| Field   | Type     | Null | Key | Default | Extra   | 
+----------------+----------------------+------+-----+---------+----------------+ 
| id    | int(11)    | NO | PRI | NULL | auto_increment | 
| ub    | varchar(30)   | NO |  | NULL |    | 
| department  | varchar(30)   | NO | MUL | NULL |    | 
| sub_department | varchar(50)   | NO | MUL | NULL |    | 
| family   | varchar(50)   | NO | MUL | NULL |    | 
| sub_family_id | smallint(5) unsigned | NO |  | NULL |    | 
| sub_family  | varchar(50)   | NO | MUL | NULL |    | 
| brand   | varchar(50)   | NO | MUL | NULL |    | 
| quartile  | smallint(5) unsigned | NO | MUL | NULL |    | 
+----------------+----------------------+------+-----+---------+----------------+ 

이 테이블에는 3604 개의 행이 있습니다.

주당 판매 수와 상점 수로 나눈 제품 당 매출 테이블 : mysql> describe backend_ubqstat;

+-----------------------+----------------------+------+-----+---------+----------------+ 
| Field     | Type     | Null | Key | Default | Extra   | 
+-----------------------+----------------------+------+-----+---------+----------------+ 
| id     | int(11)    | NO | PRI | NULL | auto_increment | 
| ubq_id    | int(11)    | YES | MUL | NULL |    | 
| week_of_year   | smallint(5) unsigned | NO | MUL | NULL |    | 
| month_of_year   | smallint(5) unsigned | NO |  | NULL |    | 
| year     | smallint(5) unsigned | NO | MUL | NULL |    | 
| store_number   | smallint(5) unsigned | NO | MUL | NULL |    | 
| nb_tickets   | smallint(5) unsigned | NO |  | NULL |    | 
| nb_items    | smallint(5) unsigned | NO |  | NULL |    | 
| revenue    | decimal(9,2)   | NO |  | NULL |    | 
| complementary_revenue | decimal(9,2)   | NO |  | NULL |    | 
+-----------------------+----------------------+------+-----+---------+----------------+ 

이 테이블에는 20 832 730 행이 있습니다.

MySQL 5.6을 사용하고 있습니다.

일부 조사를 수행했지만 문제가 해결되지 않았습니다. 첫 번째 쿼리를 훨씬 빠르게 실행하려면 어떻게해야합니까?

답변

0

열을 인덱싱하고 OR을 사용하면 최적화 프로그램이 인덱스를 사용하지 못합니다. 귀하의 경우에 week_of_year 열이 색인되지 않으면이 열을 색인화 할 수 있습니다. 이제 문제를 제거하려면 UNION을 사용하고 OR 조건을 다음과 같이 2 가지 다른 쿼리로 옮길 수 있습니다. Explain을 사용해보고 얻은 것을 확인하십시오.

SELECT 
SUM(`backend_ubqstat`.`complementary_revenue`) AS `complementary_revenue__sum`, 
SUM(`backend_ubqstat`.`revenue`) AS `revenue__sum` 
FROM `backend_ubqstat` 
INNER JOIN `backend_ubq` ON (`backend_ubqstat`.`ubq_id` = `backend_ubq`.`id`) 
WHERE 
(
    `backend_ubqstat`.`store_number` = 389 AND `backend_ubqstat`.`week_of_year` = 2 
    AND (`backend_ubq`.`department` = 'QUINCAILLERIE' OR `backend_ubq`.`department` = 'OUTILLAGE') 
    AND (`backend_ubq`.`sub_department` = 'Outillage à moteur' OR `backend_ubq`.`sub_department` = 'Outillage à main' OR `backend_ubq`.`sub_department` = 'Outil d\'assemblage') 
) 
union 
SELECT 
SUM(`backend_ubqstat`.`complementary_revenue`) AS `complementary_revenue__sum`, 
SUM(`backend_ubqstat`.`revenue`) AS `revenue__sum` 
FROM `backend_ubqstat` 
INNER JOIN `backend_ubq` ON (`backend_ubqstat`.`ubq_id` = `backend_ubq`.`id`) 
WHERE 
(
    `backend_ubqstat`.`store_number` = 389 AND `backend_ubqstat`.`week_of_year` = 3 
    AND (`backend_ubq`.`department` = 'QUINCAILLERIE' OR `backend_ubq`.`department` = 'OUTILLAGE') 
    AND (`backend_ubq`.`sub_department` = 'Outillage à moteur' OR `backend_ubq`.`sub_department` = 'Outillage à main' OR `backend_ubq`.`sub_department` = 'Outil d\'assemblage') 
) 
+0

귀하의 솔루션이 잘 작동합니다. 나는 week_of_year가 이미 색인 된 것을 확인합니다. – poiuytrez

+0

좋아요, 쿼리에서'sum'을 얻으므로 결과는 최종 합계를 위해 다시 합산되어야하는 2 행에있을 수 있습니다. –