MySQL查询花了很长时间。我尝试了很多查询变体,似乎没有任何影响速度

时间:2012-02-26 21:20:23

标签: mysql sql join

这是我的查询和结构数据:

   SELECT * 
     FROM gmm_sql as a
LEFT JOIN usds as b ON a.dp_id = b.dp_id
LEFT JOIN usdsown as c ON b.dp_id = c.dp_id 
    WHERE a.comm like '%tree%'
  • gmm_sql: 21个字段。所有字段varchar()混合在20 - 255之间。 4,882条记录。
  • usds: 7个字段。所有字段varchar()混合在20 - 255之间。 304,713条记录。
  • usdsown: 14个字段。所有字段varchar()混合在20 - 255. 107,606条记录。

我已经确认手动匹配。我正在使用MySQL Workbench来运行这些查询测试。查询只运行10分钟并且不会停止......

我做错了什么?

这是一个EXPLAIN输出:

id  select_type table   type    possible_keys   key key_len ref rows    Extra 
1   SIMPLE  a   ALL NULL    NULL    NULL    NULL    3973    Using where
1   SIMPLE  b   ALL dp_id   NULL    NULL    NULL    304345  
1   SIMPLE  c   ALL NULL    NULL    NULL    NULL    105711  

3 个答案:

答案 0 :(得分:3)

假设id字段已编入索引,这仍然可能是一个庞大的数据集。然后你在带有通配符的varchar上有一个最后的where子句......这将导致整个结果集的全表扫描,并否定a.comm字段上的任何索引。

只是好奇,但你可以通过将select *更改为'select count(a.comm)'并删除where子句来测试它。如果它仍然需要永远它是where子句,否则它是结果集的构建。

答案 1 :(得分:2)

在gmm_sql.gmm上设置 FULLTEXT 索引。 +确保已将所有外键编入索引。

WHERE a.comm like '%tree%'是您数据上最昂贵的操作。你可以用全表扫描。普通索引是不够的,因为你在匹配序列的开始处有通配符。

或者,如果您的数据库不支持此类索引,则可以使用 lucene sphynx

答案 2 :(得分:2)

我看到的第一个争论点是:

WHERE a.comm like '%tree%'

即使您在GMM_SQL.comm上有索引,通配符串左侧也会导致索引无法使用。虽然这是有效的,但它实际上是搜索数据类型与字符串相关的内容的最差表现方式。

全文搜索(MySQL specific link)是在字符串中查找内容的首选方法。但是IIRC,MySQL仍然要求表格为MyISAM ......

下一点是:

SELECT *

这将从所有的表中返回所有列,这些列是JOIN&#d; d。 SELECT子句应该只包含实际必需的列,因为:

  1. 您返回的数据超出了您的需要
  2. 数据类型可以真正搞定性能 - IE:如果其中一列是非常长的字符串,或二进制/ BLOB数据
  3. 第三 - 你的JOIN标准。数据类型越小,查询越快。我会假设id隐含INT的任何内容。如果你不需要,请不要使用BIGINT