据我所知,以下查询并不太复杂,但仍需要超过3秒。 关于如何优化这个的任何想法?
SELECT
wpp.ID, wpp.post_title, wpp.post_author,
wpp.post_status, s.supplier_company
FROM wp_posts AS wpp
LEFT JOIN wp_postmeta AS postmeta ON wpp.ID = postmeta.post_id
LEFT JOIN wp_term_relationships AS term_link ON wpp.ID = term_link.object_id
LEFT JOIN wp_terms AS terms ON term_link.term_taxonomy_id = terms.term_id
LEFT JOIN wp_teleapo_supplier AS s ON wpp.post_author = s.ID
WHERE wpp.post_type = 'post'
AND wpp.post_warning <> 'no_image'
AND wpp.post_status <> 'trash'
AND wpp.post_status <> 'auto-draft'
GROUP BY wpp.ID
ORDER BY post_date DESC
LIMIT 100 OFFSET 0
现在我的所有表格大约有2000~9000个帖子
1)wp_posts
中的15000条记录,WHERE wpp.post_type = 'post'
只有大约3000条记录
2)wp_term_relationships
中约9000左右
但是在不久的将来很容易成长......
问题的根源:
在上面的简短查询中,如果我改变:
GROUP BY wpp.ID
ORDER BY post_date DESC
要
GROUP BY wpp.ID
ORDER BY wpp.ID DESC
我的查询时间从3.3秒到0.3秒......但是我想要一种方式,所以我仍然可以ORDER BY post_date
!
甚至更奇怪的是,即使GROUP和ORDER BY不同,下面的完整搜索查询也会低于1秒......
简短查询的EXPLAIN结果:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE wpp ref type_status_date,post_type,post_status post_type 62 const 3351 Using where; Using temporary; Using filesort
1 SIMPLE postmeta ref post_id post_id 8 r_11524_jtc.wpp.ID 7 Using index
1 SIMPLE term_link ref PRIMARY PRIMARY 8 r_11524_jtc.wpp.ID 92 Using index
1 SIMPLE terms eq_ref PRIMARY PRIMARY 8 r_11524_jtc.term_link.term_taxonomy_id 1 Using index
1 SIMPLE s eq_ref ID ID 4 r_11524_jtc.wpp.post_author 1
这些是我的指数:
完全搜索取决于用户是否填写了一些搜索字段,如下所示。最奇怪的是,即使ORDER BY
列与GROUP BY
列不同,下面的搜索查询也只需0.3秒!
SELECT SQL_CALC_FOUND_ROWS wpp.ID, wpp.post_title, wpp.post_author,
wpp.post_status, s.supplier_company,
GROUP_CONCAT(DISTINCT terms.slug SEPARATOR ',') AS allslug,
GROUP_CONCAT(DISTINCT terms.name SEPARATOR ',') AS allcatname
FROM wp_posts AS wpp
LEFT JOIN wp_postmeta AS postmeta ON wpp.ID = postmeta.post_id
LEFT JOIN wp_term_relationships AS term_link ON wpp.ID = term_link.object_id
LEFT JOIN wp_terms AS terms ON term_link.term_taxonomy_id = terms.term_id
LEFT JOIN wp_teleapo_supplier AS s ON wpp.post_author = s.ID
WHERE wpp.post_type = 'post'
AND wpp.post_warning <> 'no_image'
AND wpp.post_status <> 'trash'
AND wpp.post_status <> 'auto-draft' /* All search on post_title
and any postmeta value */
AND (post_title LIKE '%textile%'
OR postmeta.meta_value LIKE '%textile%')
/* extra filters. The one below is an example of a filter on
the user #324 but this field can also take the username
(supplier_company) parameters etc. */
AND ( wpp.post_author LIKE '%324%'
OR ( EXISTS
( SELECT 1
FROM wp_teleapo_supplier as s2
WHERE s2.ID = wpp.post_author
AND (s2.supplier_company LIKE '%324%'
OR s2.supplier_company_kana LIKE '%324%') ) )
OR ( EXISTS
( SELECT 1
FROM wp_postmeta AS postmeta2
WHERE postmeta2.post_id = wpp.ID
AND postmeta2.meta_key = 'input_comp'
AND postmeta2.meta_value LIKE '%324%' ) ) )
GROUP BY wpp.ID /* Filter on Categories!! */
HAVING ( allcatname LIKE '%apparel-and-accessories%'
OR allslug LIKE '%apparel-and-accessories%' )
ORDER BY post_date DESC
LIMIT 20 OFFSET 0
答案 0 :(得分:0)
想法A
潜在问题:如果没有GROUP BY
,您是否看到一个supplier_company
的多个wpp.ID
值?如果是这样,你想要哪一个?或者你想要GROUP_CONCAT(s.supplier_company)
?
想法B
您希望NULL
出现supplier_company
吗?如果是这样,您可能会遇到这种缓慢的查询。 (并指责WP鼓励的EAV架构设计。)
如果您想跳过NULLs
,请删除所有LEFTs
。使用LEFT
,查询将收集各种NULL,但最终只会丢弃它们。
想法C
此外,如果没有LEFTs
,可能会以相反的顺序遍历表格。也就是说,从wp_teleapo_supplier
开始并查看弹出的帖子。 (可能需要更多索引才能按顺序跟踪表。)
想法D
如果不需要GROUP BY
,请将其删除并将INDEX(post_type)
替换为INDEX(post_type, post_date)
。这样,可能能够在仅找到100行时使用索引停止。或post_date
不在wpp
??? 请在JOINing
时验证所有列。
其他强>
有些评论暗示你遗漏了一些信息。在那种情况下,我的建议可能毫无用处。请不要“简化”查询。
s
没有PRIMARY KEY
?这是禁忌。请提供SHOW CREATE TABLE wp_teleapo_supplier
,以便我们讨论PK应该是什么。
更长的查询
在较长的查询中会出现许多性能杀手
LIKE '%...'
- 无法使用索引OR
- 无法使用索引。一种解决方法是将查询重新表述为UNION
,但考虑到多个ORs
,这将是一场噩梦。GROUP BY
和ORDER BY
。即使它们位于相同的列中,也会在此查询中进行太多操作以获得更多好处。OFFSET
闻起来像“分页”。SQL_CALC_FOUND_ROWS
- 查询必须完成查找所有内容。由于LIMIT
无法通过索引完成,因此无关紧要。我能想到的唯一希望是在考虑搜索的情况下重新设计架构和UI。该查询没有明显的加速。