2014-10-29 90 views
-1

我有這個表:優化MySQL查詢與布爾值

CREATE TABLE IF NOT EXISTS `products` (
    `product_id` int(11) NOT NULL AUTO_INCREMENT, 
    `supplier_id` int(11) NOT NULL, 
    `allowed` varchar(256) NOT NULL, 
    `blocked` varchar(256) NOT NULL, 
    `approved` tinyint(1) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`product_id`), 
    KEY `supplier_id` (`supplier_id`), 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

「批准」是一個布爾0/1場
「封鎖」和「允許」持有國家代碼,如「美國CA FR」

我運行此查詢:

SELECT DISTINCT supplier_id 
FROM products 
WHERE (
    supplier_id=0 OR 
    supplier_id = 1207077 OR 
    supplier_id = 1207087 OR 
    supplier_id = 1207079 OR 
    supplier_id = 1207082 OR 
    supplier_id = 1207083 OR 
    supplier_id = 1207086 OR 
    supplier_id = 1207084 OR 
    supplier_id = 1207078 OR 
    supplier_id = 1207085 OR 
    supplier_id = 1207094 OR 
    supplier_id = 1207097 OR 
    supplier_id = 1207095 OR 
    supplier_id = 1207089 OR 
    supplier_id = 1207091 
) AND (
    (`blocked` NOT LIKE '%US%' AND `allowed` ='') OR 
    `allowed` LIKE '%US%' 
) AND approved=1; 

它運行在約0.02秒。有關如何優化它的任何建議?謝謝。

+0

在supplier_id上添加索引,批准,阻止和允許。讓批准進來AND條款 – Steve 2014-10-29 23:48:59

+0

第一你也可以擺脫所有這些ORs並使用supplier_id IN(0,1207077,1207087,...) – Brian 2014-10-29 23:50:22

+0

@Brian它將在背景中是同樣的事情... won不改善表現。 – Steve 2014-10-30 00:45:29

回答

0

執行速度相同,因爲OR和非左側錨定的LIKE子句不能正確使用索引。你在美國的FR等字段中有糟糕的桌面設計,應該在你加入的另一張桌子上。如果您的設計陷入困境,表格很大,則爲supplier_id OR子句創建派生表,然後對同一個表進行JOIN,以便找到其餘匹配項。這可能還需要一個UNION,因爲你有其他的OR。欲瞭解更多信息:

http://dev.mysql.com/doc/refman/5.6/en/index-btree-hash.html 
-1

我設法優化,如下所示:

SELECT DISTINCT supplier_id FROM products WHERE ((`blocked` NOT LIKE '%US%' AND 
`allowed` ='') OR `allowed` LIKE '%US%') AND approved=1 AND supplier_id IN (1207077, 
1207087, 1207079, 1207082, 1207083, 1207086, 1207084, 1207078, 1207085, 1207094, 
1207097, 1207095, 1207089, 1207091); 

它在0.0004s現在運行。

謝謝winmutt指點我到正確的方向:-)

+0

我看到這個查詢和原始之間沒有本質區別。 – 2014-10-31 02:14:45