【问题标题】:How to optimize slow queries with hundreds of values in NOT IN?如何优化 NOT IN 中包含数百个值的慢查询?
【发布时间】:2018-02-14 22:22:38
【问题描述】:

我有两个以下两个 Wordpress 查询,它们真的很慢,我使用 Query Monitor 插件来识别。

wp_posts 表中只有不到 2400 行。

服务器有 2 个核心,平均负载在 0.5 左右

我正在使用 mysql -V 给我的 Percona 服务器:

mysql  Ver 14.14 Distrib 5.7.20-19, for Linux (x86_64) using  6.2

NOT IN 部分始终相同,大约有 400 项要排除,最多可达 1000 项

有没有办法优化查询或利用index 来加快性能?

或者有没有更好的方法来使帖子排除更有效?

SELECT wp_posts.*, (t1.meta_value+0.00) AS ratings_average, (t2.meta_value+0.00) AS ratings_users
FROM wp_posts 
LEFT JOIN wp_postmeta AS t1
ON t1.post_id = wp_posts.ID
AND t1.meta_key = 'ratings_score'
LEFT JOIN wp_postmeta As t2
ON t1.post_id = t2.post_id
AND t2.meta_key = 'ratings_users'
WHERE 1=1 
AND wp_posts.ID NOT IN (123,234,345,456,567,678,789,890)
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private') 
ORDER BY ratings_average desc, ratings_users desc
LIMIT 0, 12

SELECT p.ID AS id, p.post_title AS title, p.post_author AS uid, SUM(v.pageviews) AS pageviews
FROM `wp_popularpostssummary` v
LEFT JOIN `wp_posts` p
ON v.postid = p.ID
WHERE 1 = 1
AND p.post_type IN('post', 'page')
AND p.ID NOT IN(123,234,345,456,567,678,789,890)
AND v.view_datetime > DATE_SUB('2018-02-15 05:48:36', INTERVAL 29 DAY)
AND p.post_password = ''
AND p.post_status = 'publish'
GROUP BY v.postid
ORDER BY pageviews DESC
LIMIT 12 OFFSET 0;

【问题讨论】:

  • 您是否尝试过将这些 not in 值放在一个表中并改用它? ...但我不禁注意到,这似乎是矛盾的“NOT IN 部分总是相同的,大约有 400 项要排除,可能多达 1000 项”
  • 在任何代码中拥有不断变化的 ID 值列表并不是一个好主意。

标签: mysql wordpress percona


【解决方案1】:

尝试将值存储在一个表中,然后加入它,或者使用它的值作为 NOT IN 列表的子查询。

...
FROM wp_posts AS p
LEFT JOIN wp_posts_flagged AS f ON p.ID = f.ID -- optionally: AND f.flag_type = X
...
WHERE f.ID IS NULL
...

WHERE p.ID NOT IN (SELECT ID FROM wp_posts_flagged)

【讨论】:

  • 第二种方法WHERE p.ID NOT IN (SELECT ID FROM wp_posts_flagged) 是否与我的原始查询基本相同,其中子查询返回要在NOT IN 中使用的帖子列表?它会提高查询性能吗?
  • 虽然我不能肯定,但我很确定 MySql 的实现者会有一些优化,所以这种形式的 NOT IN 比它的原始列表形式更好。 (即便如此,我仍然会使用我提供的 JOIN 版本。)
  • 我不熟悉JOIN操作语法。我将研究它并测试实现。第一种方法中使用的可选f.flag_type = X 是什么?
  • 这只是基于我的假设,即这是为了某种黑名单功能;如果这接近正确 flag_type 将允许一个表用于多种用途“列入黑名单”可能是一种标志类型,另一种可能是“标记为审查/主持人批准”,等等......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多