添加 OR 语句时查询速度慢 MySQL
Slow MySQL query when adding an OR statement
这是我要优化的查询:
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_ubqstat
.week_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 秒。我试图了解第一个查询的主要问题是什么。
此查询计算特定商店一周内某些产品的收入总和。
I 运行 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 |
+----+-------------+-----------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+------------------------------------+------+-------------+
这些是两个 table 的架构:
Table 个产品:
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 | |
+----------------+----------------------+------+-----+---------+----------------+
这个table有3604行。
Table 每个产品的收入按周数和商店数划分:
mysql> 描述 backend_ubq统计数据;
+-----------------------+----------------------+------+-----+---------+----------------+
| 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 | |
+-----------------------+----------------------+------+-----+---------+----------------+
这个 table 有 20 832 730 行。
我正在使用 MySQL 5.6。
我做了一些研究,但找不到解决我的问题的方法。我应该怎么做才能使第一个查询 运行 更快?
当该列甚至被索引并且您使用 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')
)
这是我要优化的查询:
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_ubqstat
.week_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 秒。我试图了解第一个查询的主要问题是什么。
此查询计算特定商店一周内某些产品的收入总和。
I 运行 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 |
+----+-------------+-----------------+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------+---------+------------------------------------+------+-------------+
这些是两个 table 的架构: Table 个产品: 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 | |
+----------------+----------------------+------+-----+---------+----------------+
这个table有3604行。
Table 每个产品的收入按周数和商店数划分: mysql> 描述 backend_ubq统计数据;
+-----------------------+----------------------+------+-----+---------+----------------+
| 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 | |
+-----------------------+----------------------+------+-----+---------+----------------+
这个 table 有 20 832 730 行。
我正在使用 MySQL 5.6。
我做了一些研究,但找不到解决我的问题的方法。我应该怎么做才能使第一个查询 运行 更快?
当该列甚至被索引并且您使用 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')
)