如何提高此视图/查询的性能?

Posted

技术标签:

【中文标题】如何提高此视图/查询的性能?【英文标题】:How to increase the porformance of this View/Query? 【发布时间】:2021-02-15 03:27:48 【问题描述】:

我有一个 mysql View,它运行大约 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_MAPPING 表没有索引。

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

我将不胜感激!!!!

【问题讨论】:

如果您需要更多详细信息,请告诉我,谢谢! 在 MySQL 中针对视图的查询不能使用索引,所以性能总是会受到影响 至于更多细节,以及所有相关表的 SHOW CREATE TABLE 语句,关于查询性能的问题总是需要对给定查询的 EXPLAIN。 【参考方案1】:

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

    您还没有向我们展示表定义。

    您没有向我们展示视图定义或基础表的定义。

MySQL 查询计划器将视图定义编译到每个查询中,然后找出满足它的最佳方法。 Please read this 了解更多关于如何组合一个好的query-optimizattion 问题的信息。

说了这么多,你的查询的这些部分突然出现在我身上。

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 子句的,所以所有过滤谓词都出现在左边距附近。 (我也省略了名字周围的反引号,因为它们激怒了我。但这只是我。)

【讨论】:

谢谢。我通过在 TRIP_ASSIGNMENT_DETAILS_ID 上的 LDA_POD_TRIP_LOAD_MAPPING 表中添加索引来解决它,它提高了左连接的速度。

以上是关于如何提高此视图/查询的性能?的主要内容,如果未能解决你的问题,请参考以下文章

基于函数的索引没有提高查询性能

使用视图提高查询性能

如何使用似乎忽略索引的窗口函数提高查询的性能?

提高从 View 获取数据的查询性能

提高 Oracle 视图的性能

JAVA进阶:提高SQL性能的几种方法