【问题标题】:need help in optimizing query在优化查询方面需要帮助
【发布时间】:2021-08-26 03:00:39
【问题描述】:

其实我是用下面的查询来获取结果的,但是我觉得查询有点长,我可以帮助我优化下面的查询吗?

SELECT
    o.orderid AS id,
    sd.datestart AS startdate,
    sd.dateend AS enddate,
    o.comment AS comment,
    o.productname AS name,
    o.suspended AS sus,
    o.voided AS void,
    o.invoice_number AS inumber,
    GROUP_CONCAT(js.title) AS sections,
    GROUP_CONCAT(js.sectionid) AS sectionid,
    js.is_science_education AS isse,
    o.amount AS amount,
    js.isbundle,
    o.addedbyuserid,
    (SELECT
            COUNT(*)
        FROM
            institutiontoorder AS ito2
        WHERE
            orderid = ito.orderid) AS multiple
FROM
    institutiontoorder AS ito
        LEFT JOIN
    subscribedates AS sd ON ito.orderid = sd.orderid
        LEFT JOIN
    ordertosection AS ots ON ots.orderid = ito.orderid
        LEFT JOIN
    orders AS o ON o.orderid = ito.orderid
        LEFT JOIN
    institutions AS i ON i.institutionid = ito.institutionid
        JOIN
    journalsections AS js ON js.sectionid = ots.sectionid
WHERE
    ito.institutionid = '1419'
        AND o.voided != 1
        AND o.suspended != 1
        AND (dateend >= NOW())
GROUP BY o.orderid
ORDER BY o.orderid DESC;

我在使用多个连接,是否可以优化依赖子查询?

【问题讨论】:

  • 是否可以优化依赖子查询? 如果orderid 被索引,则无需优化。您可以尝试将其从输出列表 (SELECT) 移动到行源 (FROM),但我怀疑这会有所改善。
  • @Akina 可以不用子查询实现查询吗?
  • 没有。您需要计算未过滤行的数量。正如我从您的查询中看到的那样。
  • 恕我直言,除非您向我们提供足够的信息,否则真的很难为您提供明确的帮助。请read this,然后edit您的问题提供解决慢查询所需的信息。
  • 是否可以将o.voided != 1 AND o.suspended != 1 重写为o.voided = 0 AND o.suspended = 0?等式可以比不等式更有效地利用索引。

标签: mysql sql query-optimization


【解决方案1】:
o:    (orderid, dateend)
ito:  (institutionid, orderid)
ots:  (orderid, sectionid)
js:   (sectionid, isbundle, is_science_education, title)
i:    (institutionid)
sd:   (orderid, dateend, datestart)

列的顺序通常很重要。如果这些列中的任何一个太大(例如,如果titleTEXT),则将其关闭。否则,它们中的大多数都是“覆盖”索引,从而提供了一点额外的性能提升。

ito 列顺序对于处理 DRapp 的 ito2 很重要

【讨论】:

    【解决方案2】:

    对查询的细微调整,例如对其自己的预查询/聚合的 select count(),但仅适用于所讨论的一个机构。当您将某些 LEFT JOIN 添加到 WHERE 子句时,它们实际上变成了 INNER JOINS。

    我实际上将 AND 部分移动到了所述表的相应 JOIN 位置。

    我会确保以下索引

    table               index
    InstitutionToOrder  (institutionid, orderid)
    orders              (orderid, voided, suspended)
    subscribeDates      (orderid, dateEnd )
    OrderToSection      (orderid, sectionid )
    

    此外,您不需要到处都是“AS”,例如列 AS resultColumn 或表 A​​S 别名。隐含“AS”,分别在项目后面加一个空格。

    SELECT
            o.orderid id,
            sd.datestart startdate,
            sd.dateend enddate,
            o.comment,
            o.productname name,
            o.suspended sus,
            o.voided void,
            o.invoice_number inumber,
            GROUP_CONCAT(js.title) sections,
            GROUP_CONCAT(js.sectionid) sectionid,
            js.is_science_education isse,
            o.amount,
            js.isbundle,
            o.addedbyuserid,
            preCount.multiple
        FROM
            institutiontoorder ito
                JOIN orders o 
                    ON ito.orderid = o.orderid
                    AND o.voided = 0
                    AND o.suspended = 0
                JOIN subscribedates sd 
                    ON ito.orderid = sd.orderid
                    AND sd.dateend >= NOW()
                JOIN
                    -- pre-aggregate counts once for just the 
                    -- institution in question and join to it
                    ( SELECT
                            ito2.orderid,
                            COUNT(*) muliple
                        FROM
                            institutiontoorder ito2
                        WHERE
                            ito2.institutionid = '1419'
                        group by
                            ito2.orderid ) AS PreCount
                    on ito.orderid = PreCount.orderid
                LEFT JOIN ordertosection ots 
                    ON ito.orderid = ots.orderid
                    JOIN journalsections js 
                        ON ots.sectionid = js.sectionid
                LEFT JOIN institutions i 
                    ON ito.institutionid = i.institutionid
        WHERE
            ito.institutionid = '1419'
        GROUP BY
            -- via Transitive Property, since o.orderid = ito.orderid,
            -- use the primary table in the query's orderID for group/order by
            ito.orderid
        ORDER BY 
            ito.orderid DESC;
    

    根据 O. Jones 的 cmets,我完全同意对您订单的 VOIDED 和 SUSPENDED 过滤器进行不等式测试。这些值的选择是什么……只有 0 或 1,其中 1 表示 VOIDED 或 SUSPENDED?还是他们有其他价值。我已调整为相等 = 0(表示未作废且未暂停)

    【讨论】:

      猜你喜欢
      • 2012-06-18
      • 2013-01-03
      • 1970-01-01
      • 1970-01-01
      • 2011-08-05
      • 2012-10-14
      • 2019-06-02
      相关资源
      最近更新 更多