mysql 使用索引的查询优化

rhfm7lfc  于 2023-02-03  发布在  Mysql
关注(0)|答案(2)|浏览(123)

我需要一些帮助来优化这个WordPress/WooCommerce查询:

SELECT
    p.ID AS order_id
    ,DATE(p.post_date) AS order_date
    ,SUBSTR(comment_content,17) AS csr
    ,SUBSTR(p.post_status,4) AS order_status
    ,UCASE(CONCAT((SELECT wp_postmeta.meta_value FROM wp_postmeta WHERE meta_key = '_billing_first_name' and wp_postmeta.post_id = p.ID),' ',(SELECT wp_postmeta.meta_value FROM wp_postmeta WHERE meta_key = '_billing_last_name' and wp_postmeta.post_id = p.ID))) AS customer
    ,(SELECT GROUP_CONCAT(DISTINCT order_item_name ORDER BY order_item_name ASC SEPARATOR ', ') FROM wp_woocommerce_order_items WHERE order_id = p.ID AND order_item_type = 'line_item' GROUP BY order_id) AS products
    ,(SELECT GROUP_CONCAT(CONCAT(serial_number,'',serial_feature_code)) FROM wp_custom_serial WHERE wp_custom_serial.order_id = p.ID GROUP BY wp_custom_serial.order_id) AS serials 
FROM
    wp_posts AS p
    INNER JOIN wp_comments AS c ON p.ID = c.comment_post_ID
    INNER JOIN wp_postmeta AS pm ON p.ID = pm.post_id
    
WHERE
    p.post_type = 'shop_order'
    AND comment_content LIKE 'Order placed by%'
GROUP BY p.ID
ORDER BY SUBSTR(comment_content,17) ASC, p.post_date DESC;

我不明白EXPLAIN告诉我的是什么,需要一些关于如何加快速度的指导。有人能描述一下EXPLAIN响应中的哪些内容表明我的问题在哪里以及在哪里可以找到答案吗?
| 身份证|选择类型|桌|分区|类型|可能的密钥|键|密钥_长度|参考|行|滤过的|额外|
| - ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|- ------|
| 1个|初级|(c)秘书长的报告|零|全部|评论帖子ID|零|零|零|小行星20452|十一月十一日|使用位置;使用临时;使用文件排序|
| 1个|初级|p|零|eq_参考|主要、帖子名称、类型状态日期、帖子父代、帖子作者|初级|八个|数据库. c.备注帖子ID|1个|五十元|使用位置|
| 1个|初级|下午|零|参考|帖子标识|帖子标识|八个|数据库. c.备注帖子ID|三十三|一百元|使用指标|
| 第二章|从属子查询|wp_后元数据|零|参考|帖子ID、元密钥|帖子标识|八个|函数|三十三|二点二六|使用位置|
| 三个|从属子查询|wp_后元数据|零|参考|帖子ID、元密钥|帖子标识|八个|函数|三十三|二时三十分|使用位置|
| 四个|从属子查询|wp_woocommerce_订单_商品|零|参考|订单标识|订单标识|八个|函数|第二章|十点整|使用位置|
| 五个|从属子查询|wp_自定义_序列|零|全部|零|零|零|零|小行星5160|十点整|使用位置;使用文件排序|

i1icjdpr

i1icjdpr1#

查询是在不同的阶段中处理的。首先处理的子句是FROM子句,然后是WHERE子句,最后是SELECT子句。这些从属子查询意味着,对于在处理FROM子句和WHERE子句后“拥有”的每一行,您都要为这些结果的每行运行单独的新子查询。在您的示例中,您将执行四次此操作。
您通常可以重新执行此操作,将这些查询移出SELECT子句并移入FROM子句。
取一个列,即serials列,我认为您可能希望以如下方式将其移到FROM子句中

SELECT p.ID                                                                                  AS order_id
     , DATE(p.post_date)                                                                     AS order_date
     , SUBSTR(comment_content, 17)                                                           AS csr
     , SUBSTR(p.post_status, 4)                                                              AS order_status
     , UCASE(CONCAT((SELECT wp_postmeta.meta_value
                     FROM wp_postmeta
                     WHERE meta_key = '_billing_first_name' and wp_postmeta.post_id = p.ID), ' ',
                    (SELECT wp_postmeta.meta_value
                     FROM wp_postmeta
                     WHERE meta_key = '_billing_last_name' and wp_postmeta.post_id = p.ID))) AS customer
     , (SELECT GROUP_CONCAT(DISTINCT order_item_name ORDER BY order_item_name ASC SEPARATOR ', ')
        FROM wp_woocommerce_order_items
        WHERE order_id = p.ID
          AND order_item_type = 'line_item'
        GROUP BY order_id)                                                                   AS products
     , serials_sub.serials
FROM wp_posts AS p
         INNER JOIN wp_comments AS c ON p.ID = c.comment_post_ID
         INNER JOIN wp_postmeta AS pm ON p.ID = pm.post_id
         LEFT JOIN (
            SELECT p.ID as post_id, GROUP_CONCAT(CONCAT(cs.serial_number, '', cs.serial_feature_code)) AS serials
            FROM wp_custom_serial cs
            JOIN wp_posts AS p ON cs.order_id = p.ID
            WHERE p.post_type = 'shop_order'
             AND comment_content LIKE 'Order placed by%'
            GROUP BY cs.order_id
         ) as serials_sub ON serials_sub.post_id = p.ID
WHERE p.post_type = 'shop_order'
  AND comment_content LIKE 'Order placed by%'
GROUP BY p.ID
ORDER BY SUBSTR(comment_content, 17) ASC, p.post_date DESC;

不同之处在于,不是对每一行执行单独的查询,而是在初始FROM子句中使用单个子查询。因此,虽然看起来可能更笨拙,但实际上这将给您带来更好的性能。
对于其他子查询,我认为遵循此模式将解决您的问题。
如果有兴趣,这里是解释文档。
https://dev.mysql.com/doc/refman/8.0/en/execution-plan-information.html
而且我推荐High Performance MySQL这本书。

uqzxnwby

uqzxnwby2#

  • 似乎未使用外部wp_postmeta。如果可能,请删除JOIN。
  • 在字符串中间隐藏信息会导致SUBSTR()的使用,这是低效的。
  • GROUP BY p.ID似乎没有必要。
  • 插件WP Index Improvements将有助于某些部分。

相关问题