我有一张叫做PRODUCTS的桌子。它有一个语言字段。我想列出其他语言中缺少转录(相应ID)的language = 'es'
行。我尝试了以下(id_products是与不同语言的相同产品的行相关的关键字)。它非常慢(几千行的秒数):
SELECT
*
FROM
products AS source
LEFT JOIN products AS target ON source.id_products = target.id_products
AND source.`language` = 'es'
AND target.`language` = 'en'
WHERE
target.id_products IS NULL
答案 0 :(得分:1)
我的猜测是由于桌面上缺少索引而发生这种情况。
尝试在(id_products
,language
)上添加索引,这样可以加快查询速度。
此外,您可以尝试使用NOT EXISTS()而不是左连接,也许它会加快速度:
SELECT * FROM products t
WHERE t.language = 'es'
AND NOT EXISTS(SELECT 1 FROM products s
WHERE s.language = 'en'
and s.id_products = t.id_products)
答案 1 :(得分:1)
更好的指数
复合索引的顺序会更快:
INDEX(language, id_products)
查询将以source
开头。为此,它需要查看language = 'es'
,然后到达target
的行。对于target
,索引列的顺序无关紧要。
不要被查询缓存误导
如果您的时间小于1毫秒,您可能会从“查询缓存”中得到答案。为了测试,请通过
来避免它SELECT SQL_NO_CACHE ...
执行SELECT * ...
没有用处,因为您只需要source
列,而不是NULLs
中的所有target
。所以要么说SELECT source.*
,要么拼出你想要的列。
答案 2 :(得分:1)
在查询中进行过滤的位置有些奇怪。 您将获得所有产品的列表,无论来源是否为'es'。为了清楚起见,我总是建议将所有ON条件放在括号内。
SELECT *
FROM products AS source
LEFT JOIN products AS target
ON (source.id_products = target.id_products AND target.language = 'en')
WHERE source.language = 'es'
AND target.id_products IS NULL;
正如其他人指出的那样,你还需要一个关于源语言过滤的语言索引,并且取决于你的tabell的大小,也可以在id_products上。
alter table products add index search_index (language, id_products);
请参阅此sql fiddle以查看其实际效果。