我的查询正在执行全表扫描。
mysql> explain select dr.* from iflora_delivery_rules dr where dr.order_end_date >= "2013-05-01 09:28:05" and dr.deactive_date is null and ( (brand_id = 1 and dr.source_code in ( '1.1.1.1' , '1.1.1' , '1.1' , '1' )) or (brand_id = 0 and dr.source_code in ( '1.1.1.1' , '1.1.1' , '1.1' , '1' ))) order by precedence desc,brand_id desc,source_code desc;
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+
| 1 | SIMPLE | dr | ALL | NULL | NULL | NULL | NULL | 867 | Using where; Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+------+-----------------------------+
1 row in set (0.00 sec)
我在列brand_id,source_code
上创建了索引mysql> create index idx_brand_n1 on iflora_delivery_rules(brand_id);
Query OK, 0 rows affected (0.08 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> create index idx_source_code_n1 on iflora_delivery_rules(source_code);
Query OK, 0 rows affected (0.09 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain select dr.* from iflora_delivery_rules dr where dr.order_end_date >= "2013-05-01 09:28:05" and dr.deactive_date is null and ( (brand_id = 1 and dr.source_code in ( '1.1.1.1' , '1.1.1' , '1.1' , '1' )) or (brand_id = 0 and dr.source_code in ( '1.1.1.1' , '1.1.1' , '1.1' , '1' ))) order by precedence desc,brand_id desc,source_code desc;
+----+-------------+-------+------+---------------------------------+------+---------+------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------------------------+------+---------+------+------+-----------------------------+
| 1 | SIMPLE | dr | ALL | idx_brand_n1,idx_source_code_n1 | NULL | NULL | NULL | 867 | Using where; Using filesort |
+----+-------------+-------+------+---------------------------------+------+---------+------+------+-----------------------------+
1 row in set (0.00 sec)
表
mysql> show create table iflora_delivery_rules\G
*************************** 1. row ***************************
Table: iflora_delivery_rules
Create Table: CREATE TABLE `iflora_delivery_rules` (
`row_mod` datetime DEFAULT NULL,
`row_create` datetime DEFAULT NULL,
`delivery_rule_id` int(11) NOT NULL,
`source_code` varchar(20) COLLATE latin1_bin DEFAULT NULL,
`rotation_weight` int(11) DEFAULT NULL,
`order_start_date` datetime DEFAULT NULL,
`order_end_date` datetime DEFAULT NULL,
`order_day_of_week` varchar(7) COLLATE latin1_bin DEFAULT NULL,
`delivery_start_date` datetime DEFAULT NULL,
`delivery_end_date` datetime DEFAULT NULL,
`delivery_day_of_week` varchar(7) COLLATE latin1_bin DEFAULT NULL,
`charge_type` varchar(50) COLLATE latin1_bin NOT NULL,
`lead_min_days` int(11) NOT NULL,
`lead_max_days` int(11) NOT NULL,
`precedence` decimal(12,4) NOT NULL,
`charge_name` varchar(255) COLLATE latin1_bin DEFAULT NULL,
`amount` decimal(8,2) NOT NULL,
`display_colour` varchar(50) COLLATE latin1_bin DEFAULT NULL,
`display_long_desc` varchar(100) COLLATE latin1_bin DEFAULT NULL,
`display_short_desc` varchar(50) COLLATE latin1_bin DEFAULT NULL,
`exec_country_type` varchar(5) COLLATE latin1_bin NOT NULL,
`shipping_method_id` int(11) DEFAULT NULL,
`rule_line_id` varchar(20) COLLATE latin1_bin NOT NULL,
`deactive_date` datetime DEFAULT NULL,
`version_id` int(11) DEFAULT NULL,
`delivery_rule_type` varchar(5) COLLATE latin1_bin DEFAULT NULL,
`brand_id` int(11) DEFAULT NULL,
KEY `iflora_delivery_rules_n1` (`shipping_method_id`),
KEY `idx_exec_country_type_n1` (`exec_country_type`),
KEY `idx_rotation_weight_n1` (`rotation_weight`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin
1 row in set (0.00 sec)
答案 0 :(得分:0)
我认为WHERE子句中的OR
阻止它使用索引。由于dr.source_code
在两种情况下都相同,因此不需要在那里。此查询是等效的,应使用其中一个索引。
select dr.* from iflora_delivery_rules dr
where dr.order_end_date >= "2013-05-01 09:28:05"
and dr.deactive_date is null
and brand_id in (0, 1)
and dr.source_code in ( '1.1.1.1' , '1.1.1' , '1.1' , '1' )
order by precedence desc,brand_id desc,source_code desc;
创建复合索引可能更好:
create index idx_brand_id_source_code_n1 on iflora_delivery_rules(brand_id, source_code);
但由于您在两个字段上都使用IN
条件,因此我不确定它是否可以使用此字段。
答案 1 :(得分:0)
我试试这个
explain
SELECT dr.*
FROM iflora_delivery_rules dr
WHERE
dr.brand_id IN(1,0)
AND dr.source_code in ( '1.1.1.1' , '1.1.1' , '1.1' , '1' )
AND dr.order_end_date >= "2013-05-01 09:28:05"
AND dr.deactive_date is null
ORDER BY precedence desc, brand_id desc, source_code desc;
答案 2 :(得分:0)
虽然我不认为OR会导致问题,但很容易通过使用UNION来删除它以确认
SELECT dr.*
FROM iflora_delivery_rules dr
WHERE dr.order_end_date >= "2013-05-01 09:28:05"
AND dr.deactive_date IS NULL
AND brand_id = 1
AND dr.source_code IN ( '1.1.1.1' , '1.1.1' , '1.1' , '1' )
UNION
SELECT dr.*
FROM iflora_delivery_rules dr
WHERE dr.order_end_date >= "2013-05-01 09:28:05"
AND dr.deactive_date IS NULL
AND brand_id = 0
AND dr.source_code IN ( '1.1.1.1' , '1.1.1' , '1.1' , '1' )
ORDER BY precedence DESC,brand_id DESC,source_code DESC
但我怀疑问题可能是您选择的索引。 MySQL将仅在查询中的表上使用一个索引,因此它将选择brand_id或source_code上的索引。然而,在猜测你的例子时,选择这些都不会缩小记录的数量,因此很可能忽略了(如果索引大幅缩小了结果,那么只有MySQL才能使用索引,如果不是那么它忽略索引)。
我很想使用覆盖多列的密钥。至少是brand_id和source_code,很可能也是order_end_date。