我们发现大型WooCommerce网站运行速度非常慢。在许多问题中,这一个让我挠头。
WooComemrce将订单注释存储在comments表中,为其提供“order\\u note”的注释类型,并立即批准。它们链接到订单,因此只能由店铺管理员看到。
现在,一个站点上的某些内容(尚未跟踪)正在执行此查询:
SELECT comment_approved, COUNT(*) AS total
FROM wp_comments
GROUP BY comment_approved
系统上有120k条评论,大多数是“order\\u note”类型,这在每次页面加载上都要花费大量的时间(最多500毫秒的查询时间),并且会影响服务器。这个问题的重点是什么?它获取comments表中所有行的计数,按审批状态分组。它统计注释、trackback、ping和order\\u注释。这有什么意义?我想不出在每一页上都做这样的查询有什么用。
wp中的get\\u comment\\u count()函数包括/comment。php将运行此查询。如果您传入post ID,那么它将对该post进行汇总。这很快。如果不传入post ID,那么它会计算整个表中的所有行,这很慢,而且我也没用。此函数不接受comment\\u类型,因此不能将查询限制为特定类型的注释。
当我跟踪这个查询的来源时,我想知道为什么WP会支持这样查询整个表。这是一种假设,即永远不会创建自定义注释类型,即注释表将永远不会用于codex中列出的三种注释类型之外的任何内容。是这样吗?WooCommerce是否完全滥用了这张桌子?
我不确定我在这里寻找的是什么样的答案,但我怀疑需要在某个地方提出问题(可能是在函数中的查询WHERE子句中添加comment\\u类型),因此,我想看看这个有问题的查询有什么想法或类似的经历。
更新:
确切查询:
SELECT comment_approved, COUNT( * ) AS num_comments
FROM wp_comments
GROUP BY comment_approved
这将持续运行300mS,并返回以下结果:
|评论|已批准| num |评论| num |------------------------0 | 1 | | 1 | 191370 | |后垃圾| 1 | |垃圾邮件| 29|
优化表格后没有差异。现在我注意到count别名为“num\\u comments”,而不是“total”,这意味着正在运行的是wp\\u count\\u comments(),而不是get\\u comment\\u count()。这意味着计数结果应该缓存在key comments-0下,但事实并非如此-查询是在每个页面上运行的。可能缓存正在清除页面上的其他位置?
但是,这样做还是没有用的。大多数“批准的”评论都是WooCommerce添加的order\\u注释。它们不是通常意义上的“评论”。
comment\\u approved列被编入索引(复合索引中的第一列),WP表示它的基数为7,即使查询只返回四个组。这大约需要1mS:
SELECT DISTINCT comment_approved
FROM wp_comments
因此,索引在那里工作,但当需要计数时,它会变慢,而这实际上只需要检查索引。
解释计划是:
选择\\u type=SIMPLEtable=wp\\u CommentType=indexpossible\\u keys=NULLkey=comment\\u approved\\u date\\u gmt(?)key\\u len=70ref=NULLrows=195885Extra=使用索引
也许这只是MySQL在优化方面非常糟糕的事情之一,比如sub-select,它从第一天起就非常糟糕。
SO网友:Otto
该查询在get_comment_count()
核心功能。这个wp_count_comments()
函数运行类似的查询,但它使用wp\\u缓存系统缓存生成的数据(因此不会在每个请求中运行该代码多次)。get_comment_count()
不使用缓存。
问题是,在我看来,这是一个完全有效的查询。它这样做是为了统计被审核、批准、垃圾等评论的数量。
现在,comment\\u approved是该表中的索引键,所以实际上,查询应该非常快。当我对该查询运行EXPLAIN时,MySQL告诉我这是一个简单的select,在comment_approved_date_gmt
钥匙
因此,无论如何,它都不是一个慢查询,注释类型也不会有任何影响。如果它对您来说很慢,那么您的注释表可能有问题。索引是否正确编制?尝试在表上运行优化。尽管如此,由于该查询只应该真正命中索引,而不一定命中表,我认为这无关紧要。
查询的速度不取决于要查询的记录数,而取决于索引以及需要访问多少表才能生成结果。
如果对查询有疑问,请始终手动运行EXPLAIN以查看问题的实际情况。像这样:
EXPLAIN SELECT comment_approved, COUNT(*) AS total
FROM wp_comments
GROUP BY comment_approved
附加:请注意
comment_type
字段没有索引,因此在该字段中添加WHERE子句可能会使查询速度慢得多。这可能是一个合理的关注点,但关注点是表索引,而不是查询。