如何提高此视图/查询的性能?
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 表中添加索引来解决它,它提高了左连接的速度。以上是关于如何提高此视图/查询的性能?的主要内容,如果未能解决你的问题,请参考以下文章