2016-03-01 74 views
2

我有一個超過200萬行的表,我需要快速做一個循環中選擇查詢。MYSQL - 選擇具有多個OR條件的查詢是慢

SELECT ID,WebSite FROM `CompanyData` WHERE A1='data1' OR A2='data2' OR A3='data3' 

這需要300毫秒。我覺得它不應該花這麼多時間。下面是從查詢的解釋:

--------+---------------------------------------------------------------------------------------------------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra        | 
+----+-------------+----------+-------+---------------+------+---------+------+---------+-------------------------------------------+ 
| 1 | SIMPLE  | CompanyData | index | A1,A2,A3  | A1,A2,A3 | 153,153,153 | NULL | 3  | Using union(A1,A2,A3); Using where | 
+----+-------------+----------+-------+---------------+------+---------+------+---------+-------------------------------------------+ 

這裏是表結構:

CREATE TABLE `CompanyData` (
    `ID` int(11) NOT NULL AUTO_INCREMENT, 
    `WebSite` varchar(150) DEFAULT NULL, 
    `CompanyName` varchar(200) DEFAULT NULL, 
    `A1` varchar(150) DEFAULT NULL, 
    `A2` varchar(150) DEFAULT NULL, 
    `A3` varchar(150) DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    UNIQUE KEY `WebSite` (`WebSite`,`CompanyName`), 
    KEY `CompanyName` (`CompanyName`), 
    KEY `A1` (`A1`), 
    KEY `A2` (`A2`), 
    KEY `A3` (`A3`) 
) ENGINE=InnoDB AUTO_INCREMENT=3931223 DEFAULT CHARSET=latin1 

最近我插入另外的10萬條記錄表。然後同樣的 查詢需要大約3秒。

請提出一種改進Select查詢查找的方法。即使我準備重組桌子。

由於

+0

一般的建議是要改變的查詢和使用工會,而不是一系列的OR。然而,解釋似乎表明,MySQL已經從這方面優化了你的查詢,但是試試它並沒有什麼壞處。 – Shadow

+0

添加一個組合鍵:KEY'AX'('A1','A2','A3')。 Mysql只能使用一個鍵。 –

+2

這不會幫助! Mysql將無法使用組合鍵來滿足'OR A2 ='data2'或'A3''data3'條件,因爲每個條件僅與單個字段有關,並且組合鍵只能用於查找單個如果該單個字段是索引中最左邊的那個字段。 – Shadow

回答

3

是很困難的MySQL來優化與OR條件。您可能會更好艱難:

SELECT ID, WebSite 
FROM `CompanyData` 
WHERE A1 = 'data1' 
UNION 
SELECT ID, WebSite 
FROM `CompanyData` 
WHERE A2 = 'data2' 
UNION 
SELECT ID, WebSite 
FROM `CompanyData` 
WHERE A3 = 'data3'; 

注意,這裏使用UNION而不是UNION ALL。另一種版本UNION ALL看起來是這樣的(假設值總是NULL):

SELECT ID, WebSite 
FROM `CompanyData` 
WHERE A1 = 'data1' 
UNION ALL 
SELECT ID, WebSite 
FROM `CompanyData` 
WHERE A2 = 'data2' AND A1 <> 'data1' 
UNION ALL 
SELECT ID, WebSite 
FROM `CompanyData` 
WHERE A3 = 'data3' AND A1 <> 'data1' AND A2 <> 'data2'; 

對於此查詢,最好的指標是複合索引:(A1, ID, WebSite)(A2, A1, ID, Website),並(A3, A1, A2, ID, WebSite)

0

列間展開的數組是有問題的。

試試這個...

CREATE TABLE `CompanyData` (
    `ID` int(11) NOT NULL AUTO_INCREMENT, 
    `WebSite` varchar(150) DEFAULT NULL, 
    `CompanyName` varchar(200) DEFAULT NULL, 
    PRIMARY KEY (`ID`), 
    UNIQUE KEY `WebSite` (`WebSite`,`CompanyName`), 
    KEY `CompanyName` (`CompanyName`), 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 
CREATE TABLE `Stuff` (
    `CompanyID` int(11) NOT NULL 
    `A` varchar(150) NOT NULL, 
    PRIMARY KEY (A, CompanyID) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

SELECT c.ID, c.WebSite 
    FROM CompanyData AS c 
    JOIN Stuff AS s ON c.ID = s.CompanyID 
    WHERE s.A IN ('data1', 'data2', 'data3');