【问题标题】:MYSQL - Select query with multiple OR conditions is SlowMYSQL - 选择具有多个 OR 条件的查询很慢
【发布时间】:2016-03-02 10:55:23
【问题描述】:

我有一个超过 200 万行的表,我需要快速循环对其进行选择查询。

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

最近我又向表中插入了 1000 万条记录。然后一样 查询大约需要 3 秒。

请提出一种改进 Select 查询查找的方法。甚至我也准备好重组表格了。

谢谢

【问题讨论】:

  • 一般建议是更改查询并使用联合而不是一系列 OR。但是,解释似乎表明 mysql 已经从这方面优化了您的查询,但尝试一下并没有什么坏处。
  • 添加复合键:KEY AX (A1,A2,A3)。 Mysql只能使用一个键。
  • 那没有用! Mysql 将无法使用组合键来满足OR A2='data2' OR A3='data3' 条件,因为每个条件仅与单个字段相关,并且如果单个字段是最左侧的字段,则组合键只能用于查找单个字段索引。
  • 没有人需要“循环”进行查询。我认为问题就在那里!

标签: mysql select optimization


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    跨列展开的数组是有问题的。

    试试这个...

    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');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-04
      • 1970-01-01
      相关资源
      最近更新 更多