gpt4 book ai didi

mysql - 关于优化MySQL查询: Simple MySQL query takes more than 3 seconds

转载 作者:行者123 更新时间:2023-11-29 21:12:21 25 4
gpt4 key购买 nike

据我所知,下面的查询并不太复杂,但仍然需要 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

我所有的 table 现在大约有 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 秒内完成......

解释简短查询的结果:

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

这些是我的索引:

enter image description here

根据用户是否填写某些搜索字段的完整搜索如下。最奇怪的是,即使 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

最佳答案

想法A

潜在问题:如果没有 GROUP BY,您是否会看到一个 wpp.ID 具有多个 supplier_company 值?如果是这样,您想要哪一个?或者您想要GROUP_CONCAT(s.supplier_company)

想法B

您希望 supplier_company 出现 NULL 吗?如果是这样,您可能会陷入这个缓慢的查询。 (并归咎于 WP 鼓励的 EAV 架构设计。)

如果您想跳过NULL,请删除所有LEFT。使用LEFT,查询会收集各种 NULL,但最终会丢弃它们。

想法C

此外,如果没有LEFT,则可以按相反的顺序浏览表格。也就是说,从 wp_teleapo_supplier 开始,查看弹出哪些帖子。 (可能需要更多索引才能按该顺序遵循表格。)

想法D

如果不需要GROUP BY,请将其删除并将INDEX(post_type)替换为INDEX(post_type, post_date) 。这样,它可能能够在仅找到 100 行时使用索引停止。或者 post_date 不在 wpp 中??? 加入时限定所有列。

其他

一些评论暗示您遗漏了一些信息。在这种情况下,我的建议可能就没用了。请不要“简化”查询。

s 没有主键?这是一个禁忌。请提供SHOW CREATE TABLE wp_teleapo_supplier,以便我们可以讨论 PK 应该是什么。

更长的查询

较长的查询中会出现许多性能 killer

  • LIKE '%...' -- 无法使用索引
  • OR -- 不能使用索引。一种解决方法是将查询重新表述为 UNION,但考虑到多个 OR,这将是一场噩梦。
  • GROUP BYORDER BY 位于不同的列上。即使它们位于同一列上,此查询中也会发生太多事情,无法获得太多好处。
  • OFFSET 闻起来像“分页”。
  • SQL_CALC_FOUND_ROWS -- 查询必须完成查找所有内容。由于 LIMIT 无法通过索引完成,因此这并不重要。

我能想到的唯一希望是在考虑搜索的情况下重新设计架构和 UI。该查询不可能有显着的加速。

关于mysql - 关于优化MySQL查询: Simple MySQL query takes more than 3 seconds,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36255948/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com