如何提高这个 View/Query 的性能?

How to increase the porformance of this View/Query?

我有 Mysql 查看它 运行 大约 9 秒。我真的需要提高这个视图的性能。这是我的代码:

SELECT
        `tad`.`TRIP_ASSIGNMENT_DETAILS_ID` AS `TRIP_ASSIGNMENT_DETAILS_ID`,
        `lvdu`.`USERNAME` AS `USERNAME`,
        `cdm`.`DOMICILE_LOOK_UP_ID` AS `DOMICILE_LOOK_UP_ID`,
        CAST(
            GROUP_CONCAT(
                DISTINCT `ptlm`.`LOAD_ID` SEPARATOR ','
            ) AS CHAR(255) CHARSET utf8mb4
        ) AS `LOAD_RELATED`,
        MIN(`ptlm`.`PLANNED_START_DATETIME`) AS `PLANNED_START_DATETIME`
    FROM
           `Appian`.`LDA_TRIP_ASSIGNMENT_DETAILS` `tad`
                LEFT JOIN `Appian`.`LDA_VIEW_DRIVER_AND_USER_DETAILS` `lvdu`
                ON
                    (
                        `tad`.`DRIVER_DETAILS_ID` = `lvdu`.`DRIVER_DETAILS_ID`
                    )                    
            LEFT JOIN `Appian`.`LDA_VIEW_CARRIER_DOMICILE_MAPPING` `cdm`
            ON
                (
                    `lvdu`.`CARRIER_LOOK_UP_ID` = `cdm`.`CARRIER_LOOK_UP_ID`
                )
        LEFT JOIN `Appian`.`LDA_POD_TRIP_LOAD_MAPPING` `ptlm`
        ON
            (
                `tad`.`TRIP_ASSIGNMENT_DETAILS_ID` = `ptlm`.`TRIP_ASSIGNMENT_ID`
            )
    WHERE
        `tad`.`TRIP_STATUS` IN('Force De-Assigned', 'Completed') AND `tad`.`TRIP_ASSIGNED_TIME` > CURRENT_TIMESTAMP() - INTERVAL 10 DAY
    GROUP BY
        `tad`.`TRIP_ASSIGNMENT_DETAILS_ID`
    ORDER BY
        `tad`.`TRIP_ASSIGNMENT_DETAILS_ID`
    DESC

查看LDA_VIEW_DRIVER_AND_USER_DETAILS(1329行)LDA_VIEW_CARRIER_DOMICILE_MAPPING(216行)具有相当不错的性能和只需要0.01秒。但是一旦我 运行 这个查询大约需要 9 秒。

LDA_TRIP_ASSIGNMENT_DETAILS: 只有 19401 行

LDA_POD_TRIP_LOAD_MAPPING: 只有 11056 行

TRIP_ASSIGNMENT_DETAILS_ID是LDA_TRIP_ASSIGNMENT_DETAILS

的主键

LDA_POD_TRIP_LOAD_MAPPINGtable没有索引。

请给我一些解决这个问题的提示,

我将不胜感激!!!

需要猜测才能提供有关优化此查询的明确建议。为什么?

  1. 您还没有向我们展示 table 定义。

  2. 您没有向我们展示视图定义,或底层 table 的定义。

MySQL 查询规划器将视图定义编译到每个查询中,然后找出满足它的最佳方式。 Please read this for more information about how to put together a good 问题。

话虽这么说, 你查询的这些部分突然出现在我面前。

SELECT tad.TRIP_ASSIGNMENT_DETAILS_ID AS TRIP_ASSIGNMENT_DETAILS_ID,
....
    ON tad.DRIVER_DETAILS_ID = lvdu.DRIVER_DETAILS_ID
...
 WHERE tad.TRIP_STATUS IN('Force De-Assigned', 'Completed')
   AND tad.TRIP_ASSIGNED_TIME > CURRENT_TIMESTAMP() - INTERVAL 10 DAY
...
  ORDER BY tad.TRIP_ASSIGNMENT_DETAILS_ID DESC

如果您创建覆盖索引,它可以优化您的 WHERE 子句并为您的 SELECT 和 ON 子句提供列数据。这可能有助于您的查询 运行 快速。

这是我建议的索引

CREATE INDEX TAD_LOOKUP 
    ON Appian.LDA_TRIP_ASSIGNMENT_DETAILS 
       (TRIP_STATUS, 
        TRIP_ASSIGNED_TIME, 
        TRIP_ASSIGNMENT_DETAILS_ID DESC,
        DRIVER_DETAILS_ID);

这是 called a covering index,因为它包含满足您的查询所需的所有列。 TRIP_STATUS 是第一个,因为它在您的 WHERE 子句中显示为相等文件管理器。 TRIP_ASSIGNED_TIME 是第二个,因为它显示为范围匹配。这意味着 MySQL 可以随机访问索引到第一个相关行,然后按顺序扫描索引以获取所需的数据。

其他两列在索引中只是因为您的查询需要它们的值,而不是因为它们是搜索的一部分。

出于类似的原因,另一个索引可能也会有所帮助。

CREATE INDEX PTLM_LOOKUP 
    ON Appian.LDA_POD_TRIP_LOAD_MAPPING
     (PTLM_TRIP_ASSIGNMENT_ID, LOAD_ID);

专业提示:您和下一个处理您代码的人能够对您的查询进行推理,这一点至关重要。这意味着将它们格式化为可读是值得你花在这上面的每一秒。看看上面我是如何格式化你的 WHERE 子句的,所以所有的过滤谓词都出现在左边距附近。 (我还省略了名字周围的反引号,因为它们激怒了我。但那只是我。)