这是我的查询和结构数据:
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%'
我已经确认手动匹配。我正在使用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
答案 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子句应该只包含实际必需的列,因为:
第三 - 你的JOIN标准。数据类型越小,查询越快。我会假设id
隐含INT
的任何内容。如果你不需要,请不要使用BIGINT
。