故障排除 Wordpress/Woocommerce 自定义 SQL 报告查询
Troubleshooting Wordpress/Woocommerce custom SQL query for reporting
希望这是一个正确的论坛,我的问题似乎与堆栈交换社区重叠,所以这似乎是最好的。
我的 wordpress 网站上有一些关于我的 WooCommerce 订单的自定义报告。我有一个查询只是在本地冻结,这意味着在我的本地主机中,我的 CPU 达到 100%,而且它永远不会完成,我不明白为什么。到此为止,查询是:
SELECT SUM(postmeta.meta_value)
FROM pca_postmeta AS postmeta
LEFT JOIN pca_woocommerce_order_items AS orders ON orders.order_id = postmeta.post_id
WHERE postmeta.meta_key = '_order_total'
AND orders.order_item_id IN (
SELECT item_meta.order_item_id
FROM pca_woocommerce_order_itemmeta AS item_meta
LEFT JOIN pca_woocommerce_order_items AS orders ON item_meta.order_item_id = orders.order_item_id
LEFT JOIN pca_posts AS posts ON posts.ID = orders.order_id
WHERE item_meta.meta_value = '23563'
AND posts.post_status IN ('wc-processing','wc-completed')
GROUP BY orders.order_id
)
如您所见,此处的目标是获取此特定活动 (23563) 中所有订单的总和。嵌套查询本身完全按照预期工作,仅返回一个 ID 列表,如下所示:
注意: 有点好奇如果 2.6289 秒很长,它只返回 65 秒,尽管总共有 148220 秒
问题是这个查询似乎不喜欢嵌套部分。有什么建议么?完全不同的方法?
P.S。我在其他时候也使用该嵌套查询,在我的 php 报告 class 中按活动 ID 表示所有订单。但是对于我的问题PHP与它无关。
UPDATE/FOLLOW UP:
是否可以按照此处所述将其转换为联接:Using a SELECT statement within a WHERE clause?我对我的 SQL 有点了解,所以不确定我该怎么做,但看起来很有希望
GROUP BY orders.order_id
没有意义,因为您只选择了 order_item_id
。
pca_woocommerce_order_itemmeta
会受益于
INDEX(meta_value, order_item_id)
这个 可能 是一个等效的查询,但避免了 IN(SELECT...)
:
SELECT SUM(pm.meta_value)
FROM
( SELECT im.order_item_id
FROM pca_woocommerce_order_itemmeta AS im
LEFT JOIN pca_woocommerce_order_items AS o
ON im.order_item_id = o.order_item_id
LEFT JOIN pca_posts AS posts ON posts.ID = o.order_id
WHERE im.meta_value = '23563'
AND posts.post_status IN ('wc-processing','wc-completed')
GROUP BY o.order_id
) AS w
JOIN pca_woocommerce_order_items AS o ON w.order_item_id = o.order_item_id
JOIN pca_postmeta AS pm ON o.order_id = pm.post_id
WHERE pm.meta_key = '_order_total'
编辑
我所做的一些原则。在这里,我猜测优化器将如何处理各种可能的查询公式。
- 我去掉了
LEFT
-- 这 可能 改变了输出。但是我需要避免无法优化的 LEFT JOIN ( SELECT ... )
。
- 通过在 "tables" 的列表中加入 一个 子查询,优化器将(几乎可以肯定)从子查询开始并执行 "Nested Loop Joins" 到其他tables。 NLJ 是执行查询的常用方法。
- 像这样的subselect是没有索引的,所以需要排在第一位,否则效率很低
- 在没有子查询的情况下,优化器通常喜欢从 table 在
WHERE
子句中包含的内容开始。
- 从子查询"table"开始的要求强于基于
WHERE pm.meta_key = '_order_total'
选择table的愿望。
- 在子查询中,唯一的“=”测试 (
WHERE im.meta_value = '23563
) 为该组 JOIN 提供了可能的起点。由于它不是 LEFT JOIN
的 'right',因此进一步增强了这一点。因此,我建议 index.
希望这是一个正确的论坛,我的问题似乎与堆栈交换社区重叠,所以这似乎是最好的。
我的 wordpress 网站上有一些关于我的 WooCommerce 订单的自定义报告。我有一个查询只是在本地冻结,这意味着在我的本地主机中,我的 CPU 达到 100%,而且它永远不会完成,我不明白为什么。到此为止,查询是:
SELECT SUM(postmeta.meta_value)
FROM pca_postmeta AS postmeta
LEFT JOIN pca_woocommerce_order_items AS orders ON orders.order_id = postmeta.post_id
WHERE postmeta.meta_key = '_order_total'
AND orders.order_item_id IN (
SELECT item_meta.order_item_id
FROM pca_woocommerce_order_itemmeta AS item_meta
LEFT JOIN pca_woocommerce_order_items AS orders ON item_meta.order_item_id = orders.order_item_id
LEFT JOIN pca_posts AS posts ON posts.ID = orders.order_id
WHERE item_meta.meta_value = '23563'
AND posts.post_status IN ('wc-processing','wc-completed')
GROUP BY orders.order_id
)
如您所见,此处的目标是获取此特定活动 (23563) 中所有订单的总和。嵌套查询本身完全按照预期工作,仅返回一个 ID 列表,如下所示:
注意: 有点好奇如果 2.6289 秒很长,它只返回 65 秒,尽管总共有 148220 秒
问题是这个查询似乎不喜欢嵌套部分。有什么建议么?完全不同的方法?
P.S。我在其他时候也使用该嵌套查询,在我的 php 报告 class 中按活动 ID 表示所有订单。但是对于我的问题PHP与它无关。
UPDATE/FOLLOW UP:
是否可以按照此处所述将其转换为联接:Using a SELECT statement within a WHERE clause?我对我的 SQL 有点了解,所以不确定我该怎么做,但看起来很有希望
GROUP BY orders.order_id
没有意义,因为您只选择了 order_item_id
。
pca_woocommerce_order_itemmeta
会受益于
INDEX(meta_value, order_item_id)
这个 可能 是一个等效的查询,但避免了 IN(SELECT...)
:
SELECT SUM(pm.meta_value)
FROM
( SELECT im.order_item_id
FROM pca_woocommerce_order_itemmeta AS im
LEFT JOIN pca_woocommerce_order_items AS o
ON im.order_item_id = o.order_item_id
LEFT JOIN pca_posts AS posts ON posts.ID = o.order_id
WHERE im.meta_value = '23563'
AND posts.post_status IN ('wc-processing','wc-completed')
GROUP BY o.order_id
) AS w
JOIN pca_woocommerce_order_items AS o ON w.order_item_id = o.order_item_id
JOIN pca_postmeta AS pm ON o.order_id = pm.post_id
WHERE pm.meta_key = '_order_total'
编辑
我所做的一些原则。在这里,我猜测优化器将如何处理各种可能的查询公式。
- 我去掉了
LEFT
-- 这 可能 改变了输出。但是我需要避免无法优化的LEFT JOIN ( SELECT ... )
。 - 通过在 "tables" 的列表中加入 一个 子查询,优化器将(几乎可以肯定)从子查询开始并执行 "Nested Loop Joins" 到其他tables。 NLJ 是执行查询的常用方法。
- 像这样的subselect是没有索引的,所以需要排在第一位,否则效率很低
- 在没有子查询的情况下,优化器通常喜欢从 table 在
WHERE
子句中包含的内容开始。 - 从子查询"table"开始的要求强于基于
WHERE pm.meta_key = '_order_total'
选择table的愿望。 - 在子查询中,唯一的“=”测试 (
WHERE im.meta_value = '23563
) 为该组 JOIN 提供了可能的起点。由于它不是LEFT JOIN
的 'right',因此进一步增强了这一点。因此,我建议 index.