【问题标题】:this Query is taking 15 seconds此查询需要 15 秒
【发布时间】:2019-08-01 15:18:19
【问题描述】:

我也添加了索引,但仍然需要 13 秒

我为我在这里使用的所有列添加了复合索引

SELECT carrierbil2_.IDENTITY AS col_0_0_,
        carrier4_.CARRIER_NAME AS col_1_0_,
        carrier4_.IDENTITY AS col_2_0_,
        carrier4_.CARRIER_ID AS col_3_0_,
        shipmentor0_.EXTERNAL_REFERENCE_ID AS col_4_0_,
        invoicedet5_.INVOICE_NUMBER AS col_5_0_,`enter code here`
        shipmentca1_.CARRIER_REFERENCE_NUMBER AS col_6_0_,
        SUM(shipmentco9_.RATED_COST) AS col_7_0_,
        SUM(shipmentco9_.COST) AS col_8_0_,
        invoice6_.TOTAL_PAID_AMOUNT AS col_9_0_,
        invoice6_.INVOICE_GENERATED_DATE AS col_10_0_,
        shipmentor0_.ACTUAL_SHIP_DATE AS col_11_0_,
        bolstatus15_.BOL_STATUS_ID AS col_12_0_,
        shipmentlo10_.LOCATION_NAME AS col_13_0_,
        country11_.COUNTRY_NAME AS col_14_0_,
        postal14_.POSTAL_CODE AS col_15_0_,
        state12_.STATE_NAME AS col_16_0_,
        city13_.CITY_NAME AS col_17_0_,
        shipmentlo16_.LOCATION_NAME AS col_18_0_,
        country17_.COUNTRY_NAME AS col_19_0_,
        postal20_.POSTAL_CODE AS col_20_0_,
        state18_.STATE_NAME AS col_21_0_,
        city19_.CITY_NAME AS col_22_0_,
        shipmentor0_.IDENTITY AS col_23_0_,
        shipmentca1_.IDENTITY AS col_24_0_,
        shipmentno7_.NOTE AS col_25_0_
    FROM
        SHIPMENT_ORDER shipmentor0_
            INNER JOIN
        SHIPMENT_CARRIER shipmentca1_ ON shipmentor0_.SHIPMENT_ORDER_ID = shipmentca1_.SHIPMENT_ORDER_ID
            AND (shipmentca1_.IS_DELETED = 0)
            LEFT OUTER JOIN
        CARRIER_BILL_DETAILS carrierbil2_ ON shipmentca1_.SHIPMENT_CARRIER_ID = carrierbil2_.SHIPMENT_CARRIER_ID
            LEFT OUTER JOIN
        CARRIER_BILLS carrierbil3_ ON carrierbil2_.CARRIER_BILL_ID = carrierbil3_.CARRIER_BILL_ID
            INNER JOIN
        CARRIER carrier4_ ON shipmentca1_.CARRIER_ID = carrier4_.CARRIER_ID
            LEFT OUTER JOIN
        INVOICE_DETAILS invoicedet5_ ON shipmentor0_.SHIPMENT_ORDER_ID = invoicedet5_.SHIPMENT_ORDER_ID
            LEFT OUTER JOIN
        INVOICE invoice6_ ON invoicedet5_.INVOICE_ID = invoice6_.INVOICE_ID
            LEFT OUTER JOIN
        SHIPMENT_NOTES shipmentno7_ ON shipmentor0_.SHIPMENT_ORDER_ID = shipmentno7_.SHIPMENT_ORDER_ID
            AND (shipmentno7_.NOTE_TYPE = 4)
            LEFT OUTER JOIN
        SHIPMENT_COST shipmentco8_ ON shipmentor0_.SHIPMENT_ORDER_ID = shipmentco8_.SHIPMENT_ID
            LEFT OUTER JOIN
        SHIPMENT_COST_DETAILS shipmentco9_ ON shipmentco8_.SHIPMENT_COST_ID = shipmentco9_.SHIPMENT_COST_ID
            AND (shipmentco9_.IS_DELETED = 0)
            LEFT OUTER JOIN
        SHIPMENT_LOCATION shipmentlo10_ ON shipmentor0_.ORIGIN_ID = shipmentlo10_.SHIPMENT_LOCATION_ID
            AND (shipmentlo10_.LOCATION_TYPE_ID = 3)
            LEFT OUTER JOIN
        COUNTRY country11_ ON shipmentlo10_.COUNTRY_ID = country11_.COUNTRY_ID
            LEFT OUTER JOIN
        STATE state12_ ON shipmentlo10_.STATE_ID = state12_.STATE_ID
            LEFT OUTER JOIN
        CITY city13_ ON shipmentlo10_.CITY_ID = city13_.CITY_ID
            LEFT OUTER JOIN
        POSTAL postal14_ ON shipmentlo10_.POSTAL_ID = postal14_.POSTAL_ID
            LEFT OUTER JOIN
        BOL_STATUS bolstatus15_ ON shipmentor0_.ORDER_STATUS = bolstatus15_.BOL_STATUS_ID
            LEFT OUTER JOIN
        SHIPMENT_LOCATION shipmentlo16_ ON shipmentor0_.DESTINATION_LOCATION_ID = shipmentlo16_.SHIPMENT_LOCATION_ID
            AND (shipmentlo16_.LOCATION_TYPE_ID = 4)
            LEFT OUTER JOIN
        COUNTRY country17_ ON shipmentlo16_.COUNTRY_ID = country17_.COUNTRY_ID
            LEFT OUTER JOIN
        STATE state18_ ON shipmentlo16_.STATE_ID = state18_.STATE_ID
            LEFT OUTER JOIN
        CITY city19_ ON shipmentlo16_.CITY_ID = city19_.CITY_ID
            LEFT OUTER JOIN
        POSTAL postal20_ ON shipmentlo16_.POSTAL_ID = postal20_.POSTAL_ID
            CROSS JOIN
        CLIENT client21_
    WHERE
        shipmentor0_.CLIENT_ID = client21_.CLIENT_ID
            AND bolstatus15_.SEQUENCE_ID >= 700
            AND (carrierbil3_.IS_APPROVED = 0
            OR carrierbil3_.IS_APPROVED IS NULL)
            AND (carrierbil3_.IS_DELETED = 0
            OR carrierbil3_.IS_DELETED IS NULL)
            AND (carrierbil2_.IS_DELETED = 0
            OR carrierbil2_.IS_DELETED IS NULL)
            AND (shipmentor0_.IS_DELETED = 0
            OR shipmentor0_.IS_DELETED IS NULL)

    GROUP BY invoice6_.INVOICE_GENERATED_DATE , shipmentca1_.IDENTITY  , invoicedet5_.INVOICE_NUMBER , invoice6_.TOTAL_PAID_AMOUNT , shipmentca1_.CARRIER_REFERENCE_NUMBER , carrier4_.CARRIER_ID , CAST(carrier4_.IDENTITY AS SIGNED) , carrier4_.CARRIER_NAME , CAST(carrierbil2_.IDENTITY AS SIGNED) , shipmentor0_.SHIPMENT_ORDER_ID , shipmentno7_.NOTE , shipmentor0_.EXTERNAL_REFERENCE_ID , shipmentlo10_.LOCATION_NAME , country11_.COUNTRY_NAME , postal14_.POSTAL_CODE , state12_.STATE_NAME , city13_.CITY_NAME , shipmentlo16_.LOCATION_NAME , country17_.COUNTRY_NAME , postal20_.POSTAL_CODE , state18_.STATE_NAME , city19_.CITY_NAME , shipmentor0_.IDENTITY 
    ORDER BY shipmentor0_.SHIPMENT_ORDER_ID DESC;

【问题讨论】:

  • 你真的需要使用LEFT JOIN吗?我注意到你有 non IS NULL 在LEFT JOINED 表上签入WHERE,这些表应该在ON 子句中,如bolstatus15_.SEQUENCE_ID >= 700 和carrierbil3_.IS_APPROVED = 0 给出几个例子那些带有错误过滤器的LEFT JOINED 表现在将像INNER JOIN 一样工作
  • 使用explain analyze 编辑。找到postgres的explain analyze的mysql等价物
  • explain analyse 接缝为 PostgreSQL 语法 @mistahenry MySQL 不知道explain 中的analyse
  • 还要添加到@mistahenry 的评论中,您应该为查询中涉及的每个表提供表结构SHOW CREATE TABLE table
  • 您没有向我们提供足够的信息来帮助您。请阅读:meta.stackoverflow.com/a/271056 请特别注意查询性能部分。那么请edit你的问题。

标签: mysql query-performance


【解决方案1】:

索引大多是无用的,因为OR,如

        AND (carrierbil3_.IS_APPROVED = 0
          OR carrierbil3_.IS_APPROVED IS NULL)

解决这个问题的简单方法是选择 either 0 或 NULL 来表示标志。然后确保所有数据一致,并将WHERE 更改为仅检查一种情况。

你真的是什么意思

        CROSS JOIN
    CLIENT client21_

这可能会影响性能并产生巨大的结果集。

没关系。 WHERE 中有 ON。关系请使用ON,过滤请使用WHERE。

  WHERE
    shipmentor0_.CLIENT_ID = client21_.CLIENT_ID

我看到LEFT JOIN 和JOIN 的混合。检查LEFT JOINs 是否真的需要为LEFT;也就是说,“正确”表可能缺少数据。

如需进一步讨论,请提供EXPLAIN SELECT ...。

避免过度标准化:

您有 5 个表格来描述一个位置(名称、国家/地区、邮政、州、城市)。相反,我推荐一个包含这 5 列的 single 表。仅此一项,就可以摆脱 8 个JOINs。

CAST(carrier4_.IDENTITY AS SIGNED) -- 你不能将数据类型固定为SIGNED,或者允许值是UNSIGNED吗?

但也许主要的性能杀手是“爆炸-内爆”综合症。首先,它做了很多JOINs,构建了一个巨大的中间表,然后它通过GROUP BY 折叠了它。补救措施是

SELECT ...
    FROM ( SELECT SUM(...), SUM(...) FROM ... GROUP BY ... ) AS a
    JOIN ((whatever else is needed));

也就是说,首先设计一个最小的“派生表”来执行GROUP BY(和/或ORDER BY 和/或LIMIT)。然后看看完成查询还需要什么(即所有规范化查找)。

在你对我的大部分 cmets 进行了操作之后,我们可以讨论你是否有最优的索引。 (现在这样做还为时过早。)如果是这样,请开始一个新问题;添加到这个会太混乱了。

【讨论】:

    【解决方案2】:

    首先,有很多连接。但是,您的查询花费大量时间的主要原因是您添加了 order by 子句。你需要想办法避免它,或者可能想出不同的策略

    【讨论】:

    • “但是,您的查询花费大量时间的主要原因是因为您正在添加一个 order by 子句” 您在这里猜测您不知道该表结构,所以你不知道索引在哪里。或者 ORDER BY 是否可以按索引排序。
    • 我不认为 ORDER BY 子句是 GROUP BY 查询的瓶颈。
    • @Paul Spiegel 错过了 group by 子句,你是对的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 2019-02-18
    • 2012-12-16
    • 2011-03-25
    • 2011-10-23
    • 1970-01-01
    相关资源
    最近更新 更多