SLOW QUERY / IN HAVING 子句
SLOW QUERY / IN HAVING Clause
我在MySQL
中有一个多对多关系数据库
而这个查询:
SELECT main_id FROM posts_tag
WHERE post_id IN ('134','140','187')
GROUP BY main_id
HAVING COUNT(DISTINCT post_id) = 3
此 table 中有 ~5,300,000 行并且该查询似乎很慢 5 秒(而且更慢如果我在搜索中添加更多 ID)
想请问有没有什么办法可以让它更快?
EXPLAIN 显示:
顺便说一句,我想添加更多条件,例如 NOT IN 和可能的 JOIN 新 tables,它们具有相同的结构但不同的数据。不太像这样,但首先我想知道是否有任何方法可以使这个简单的查询更快?
任何建议都会有所帮助,甚至是另一种方法或结构等。
PS:硬件是 Intel Core i9 3.6Ghz、64GB RAM、480GB SSD。所以我认为服务器规格不是问题。
使用“复合”和“覆盖”索引:
INDEX(post_id, main_id)
并删除 INDEX(post_id)
,因为它会变得多余。
“覆盖”有助于加快查询速度。
假设这是一个正常的“多对多” table,那么:
CREATE TABLE post_main (
post_id -- similar to `id` in table `posts`
main_id -- similar to `id` in table `main`
PRIMARY KEY(post_id, main_id),
INDEX(main_id, post_id)
) ENGINE=InnoDB;
在多对多 table 中的任何地方都不需要 AUTO_INCREMENT
。
(您可以添加 FK 约束,但我说 'why bother'。)
更多讨论:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table
不在
这有点棘手。我认为这是一种方式;可能还有其他人。
SELECT main_id
FROM post_main
WHERE post_id IN (244,229,193,93,61)
GROUP BY main_id AS x
HAVING COUNT(*) = 5
AND NOT EXISTS ( SELECT 1
FROM post_main
WHERE main_id = x.main_id
AND post_id IN (92,10,234) );
Alexfsk,您在第二行的查询中的 IN 变量被单引号括起来。当您的列名定义为 INT 或 mediumint(或任何类型的 int)数据类型时,在数据周围添加单引号会导致考虑的每一行的数据类型转换延迟并延迟查询的完成。
我在MySQL
中有一个多对多关系数据库而这个查询:
SELECT main_id FROM posts_tag
WHERE post_id IN ('134','140','187')
GROUP BY main_id
HAVING COUNT(DISTINCT post_id) = 3
此 table 中有 ~5,300,000 行并且该查询似乎很慢 5 秒(而且更慢如果我在搜索中添加更多 ID)
想请问有没有什么办法可以让它更快?
EXPLAIN 显示:
顺便说一句,我想添加更多条件,例如 NOT IN 和可能的 JOIN 新 tables,它们具有相同的结构但不同的数据。不太像这样,但首先我想知道是否有任何方法可以使这个简单的查询更快?
任何建议都会有所帮助,甚至是另一种方法或结构等。
PS:硬件是 Intel Core i9 3.6Ghz、64GB RAM、480GB SSD。所以我认为服务器规格不是问题。
使用“复合”和“覆盖”索引:
INDEX(post_id, main_id)
并删除 INDEX(post_id)
,因为它会变得多余。
“覆盖”有助于加快查询速度。
假设这是一个正常的“多对多” table,那么:
CREATE TABLE post_main (
post_id -- similar to `id` in table `posts`
main_id -- similar to `id` in table `main`
PRIMARY KEY(post_id, main_id),
INDEX(main_id, post_id)
) ENGINE=InnoDB;
在多对多 table 中的任何地方都不需要 AUTO_INCREMENT
。
(您可以添加 FK 约束,但我说 'why bother'。)
更多讨论:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table
不在
这有点棘手。我认为这是一种方式;可能还有其他人。
SELECT main_id
FROM post_main
WHERE post_id IN (244,229,193,93,61)
GROUP BY main_id AS x
HAVING COUNT(*) = 5
AND NOT EXISTS ( SELECT 1
FROM post_main
WHERE main_id = x.main_id
AND post_id IN (92,10,234) );
Alexfsk,您在第二行的查询中的 IN 变量被单引号括起来。当您的列名定义为 INT 或 mediumint(或任何类型的 int)数据类型时,在数据周围添加单引号会导致考虑的每一行的数据类型转换延迟并延迟查询的完成。