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  | 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)
4

3 回答 3

0

我认为ORWHERE 子句中的 阻止它使用索引。由于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在两个字段上都使用了条件,所以我不确定它是否能够使用它。

于 2013-05-02T06:22:34.417 回答
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;
于 2013-05-02T06:24:50.803 回答
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。

于 2013-05-02T09:05:21.673 回答