2013-05-02 35 views
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) 
+0

請重新格式化:http://stackoverflow.com/editing-help – 2013-05-02 06:03:26

+0

'source_code'在'OR'的兩個部分是相同的,你需要重複嗎?我認爲將它從「OR」中解放出來可以解決問題。 – Barmar 2013-05-02 06:18:17

回答

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條件,我不知道這是否將能夠使用此。

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; 
0

雖然我不認爲應該或導致出現問題,很容易消除這種通過使用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。