添加OR语句时,MySQL查询速度慢

时间:2015-01-23 13:26:26

标签: mysql performance join indexing

这是我想要优化的查询:

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 OR `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'));

此查询需要73秒才能执行。只有一周的同一查询(backend_ubqstatweek_of_year = 2,没有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秒才能执行。我试图了解第一个查询的主要问题是什么。

此查询计算特定商店中某些产品在一周内的收入总和。

我使用这些结果在两个查询上运行了EXPLAIN:

多周(第一次查询):

+----+-------------+-----------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+------------------------------------+------+------------------------------------+
| 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 |
+----+-------------+-----------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+------------------------------------+------+-------------+

这些是两个表的架构: 产品表: MySQL的>描述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的>描述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。

我做了一些研究,但我无法找到解决问题的方法。我需要做些什么才能使第一个查询运行得更快?

1 个答案:

答案 0 :(得分: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')
)