我正在使用Industrialthemes的WordPress主题引擎,并看到首页的呈现使用了大量查询,在我的MySQL数据库中运行大约需要0.4秒。像这个:
SELECT SQL_NO_CACHE SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
WHERE 1 =1
AND (wp_term_relationships.term_taxonomy_id IN (1))
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'closed')
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 5;
有什么方法可以改进这个查询吗?据我所见,WordPress安装为所有涉及的字段都设置了默认索引。我在调优SQL Select语句方面的知识并不好,所以我希望一些专家能在这方面帮助我。谢谢
(来自评论(
CREATE TABLE wp_term_relationships (
object_id bigint(20) unsigned NOT NULL DEFAULT '0',
term_taxonomy_id bigint(20) unsigned NOT NULL DEFAULT '0',
term_order int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (object_id,term_taxonomy_id),
KEY term_taxonomy_id (term_taxonomy_id),
KEY idx1 (object_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
(稍后…(
CREATE TABLE wp_term_relationships (
object_id bigint(20) unsigned NOT NULL DEFAULT '0',
term_taxonomy_id bigint(20) unsigned NOT NULL DEFAULT '0',
term_order int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (object_id,term_taxonomy_id),
KEY term_taxonomy_id (term_taxonomy_id),
KEY idx1 (term_taxonomy_id,object_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
wp_term_relationships needs INDEX(term_taxonomy_id, object_id) -- in this order
wp_posts might benefit from INDEX(post_type, ID, post_status, post_date) -- in this order
两者都是"覆盖"指数
前者使JOIN
有效地工作,为优化器提供了从wp_term_relationships
开始的选项。它应该取代KEY term_taxonomy_id (term_taxonomy_id)
无论先选择哪一张表,后者都应该能很好地工作。
(更多(
SELECT SQL_NO_CACHE SQL_CALC_FOUND_ROWS p.ID
FROM wp_posts AS p
WHERE p.post_type = 'post'
AND p.post_status IN ( 'publish', 'closed' )
AND EXISTS ( SELECT 1 FROM wp_term_relationships AS tr
WHERE p.ID = tr.object_id
AND tr.term_taxonomy_id IN (1) )
ORDER BY p.post_date DESC
LIMIT 0, 5;
使用这种配方,
如果EXPLAIN以p:开头
p: (post_date, post_type, post_status, ID)
p: (post_type, post_status, ID, post_date)
tr: (object_id, term_taxonomy_id) -- which you have
如果EXPLAIN以tr:开头
p: (ID) -- which you probably have
tr: (term_taxonomy_id, object_id)
主要问题:
GROUP BY
正在加大力度。(我通过将JOIN
更改为EXISTS
来消除它。(IN ( 'publish', 'closed' )
——抑制指标的有效使用SQL_CALC_FOUND_ROWS
——意味着当它得到5行时不能停止IN (1)
变成= 1
,这是好的;但CCD_ 11更混乱
或者,更直白地说,WP还没有被设计成规模。
请添加索引并获得EXPLAIN SELECT
。
来自pastebin:
SELECT SQL_NO_CACHE p.ID
FROM wp_posts AS p
WHERE p.post_type = 'post'
AND p.post_status = 'publish'
AND EXISTS
(
SELECT 1
FROM wp_term_relationships AS tr
WHERE p.ID = tr.object_id
AND EXISTS
(
SELECT 1
from wp_term_taxonomy AS tt
WHERE tr.term_taxonomy_id = tt.term_taxonomy_id
AND tt.taxonomy = 'post_tag'
AND tt.term_id IN (548, 669) )
);
这是一个不同的查询。它还需要这个:
tt: INDEX(term_taxonomy_id, taxonomy, -- in either order
term_id) -- last
而且。。。
SELECT SQL_NO_CACHE wp_posts.ID
FROM wp_posts
INNER JOIN wp_term_relationships tr
ON (wp_posts.ID = tr.object_id)
INNER JOIN wp_term_taxonomy tt
ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
WHERE ( post_type = 'post'
AND post_status = 'publish'
AND tt.taxonomy = 'post_tag'
AND tt.term_id IN (548, 669)
)
GROUP BY wp_posts.ID;
需要
tt: INDEX(taxonomy, term_id, term_taxonomy_id) -- in this order
我将把这两个索引都添加到tt
中,看看EXPLAINs
和性能会发生什么变化。
重写查询查看这是否给出了"正确"答案:
SELECT p.ID, p.post_name, p.post_title,
p.post_type, p.post_status,
tt.term_id as termid, tt.taxonomy
FROM wp_posts AS p
INNER JOIN wp_term_relationships tr ON (p.ID = tr.object_id)
INNER JOIN wp_term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
WHERE p.post_type = 'post'
AND p.post_status = 'publish'
AND tt.taxonomy = 'post_tag'
AND tt.term_id IN (548, 669)
ORDER BY p.ID;
注:
GROUP BY
已删除- AND/OR可能没有按预期工作:
a AND b OR c
相当于(a AND b) OR c
,但我认为您想要a AND (b OR c)
- 你添加了推荐的索引了吗