mysql - 具有多个左连接的查询花费太长时间

问题描述 投票:0回答:2

我正在尝试使用在多个表上留下连接的查询来获取数据。该查询返回 4132 行,持续时间为 4.55 秒,在

mysql workbench
中提取需要 31.30 秒。我什至尝试从
php
执行它,但这需要相同的时间。

SELECT
                aa.bams_id AS chassis_bams_id, aa.hostname AS chassis_hostname, 
    aa.rack_number AS chassis_rack, aa.serial_number AS chassis_serial, aa.site_id AS chassis_site_id,
    cb.bay_number, cb.bsn AS serial_number_in_bay,
CASE
                WHEN a_a.bams_id IS NULL THEN 'Unknown'
                ELSE a_a.bams_id
END AS blade_bams_id,
                a_a.hostname AS blade_hostname, a_s.description AS blade_status, a_a.manufacturer AS blade_manufacturer, a_a.model AS blade_model,
                a_a.bookable_unit_id AS blade_bookable_unit_id, a_a.rack_number AS blade_rack_number, a_a.manufactured_date AS blade_manufactured_date,
                a_a.support_expired_date AS blade_support_expired_date, a_a.site_id AS blade_site_id
FROM all_assets aa
                LEFT JOIN manufacturer_model mm ON aa.manufacturer = mm.manufacturer AND aa.model = mm.model
                LEFT JOIN chassis_bays cb ON aa.bams_id = cb.chassis_bams_id
                LEFT JOIN all_assets a_a ON cb.bsn = a_a.serial_number
                LEFT JOIN asset_status a_s ON a_a.status=a_s.status
WHERE mm.hardware_type = 'chassis';

这些是所使用的表的定义:

EXPLAIN
的输出:

查询获取每个机箱内每个刀片的数据。 在其他系统上执行相同的查询,只需要5秒即可获取结果。

如何优化此查询?

更新(已解决)

按照专家的建议添加了此处的索引。 下面是添加索引后的执行计划。

mysql sql mysql-workbench
2个回答
1
投票

创建索引,非索引读取比索引读取慢。

要准确确定导致性能下降的原因,最好的工具 就是使用“查询计划分析器”:

看这里: mySql性能讲解

尝试在将要发生的最明显的读取上创建索引。查看在加入时发挥作用的字段以及 where 子句。如果您在这些字段上有索引,如果发生非索引读取,您的性能应该会提高。

如果这仍然是一个问题,最好看看 mySQL 如何获取数据, 有时会重组您的数据,甚至可能改变您的排队方式 可以给你更好的结果。

例如。创建索引:aa.manufacturer_model、aa.manufacturer、aa.model 和 mm.hardware_type


0
投票

类似问题

我有一个

user
s 表,与其他表有很多关系:21
LEFT JOIN
s
。 该查询不仅花费了很长时间,而且还导致我的 NodeJS 服务器崩溃,并出现“JS 堆内存不足”...

我的解决方案

我的解决方案是将一些

left join
转换为使用
sub query
JSON_ARRAYAGG
GROUP BY

备注:

  • 我之前尝试将左连接更改为右连接,但结果是“空集”。
  • 就我个人而言,我无法在 1 个 TypeORM QueryBuilder 中完成它,所以我有 2 个查询来获取
    user
    的数据。

我的解决方案的代码

  • 该代码非常适合我的需求,但总体思路是将“左连接”更改为带有
    sub query
    group by
    (如果适合您)的
    JSON_ARRAYAGG
    。 (当然还有 JSON.parse()。(JS))
  • 注意:这是TypeORM的QueryBuilder语法,但我认为它很容易理解并转换为纯MySQL查询
  • 用户===治疗师

我有多对多的关系。这意味着 2

LEFT JOIN
s

上一篇:

LEFT JOIN `therapists_treatment_qualifications` `therapist_treatmentQualifications` ON `therapist_treatmentQualifications`.`user_id` = `therapist`.`id`
LEFT JOIN `treatment_qualification` `treatmentQualifications` ON `treatmentQualifications`.`id` = `therapist_treatmentQualifications`.`treatment_qualification_id`

解决方案:

// "query 1":
const therapist = await this.therapistRepository.createQueryBuilder('therapist');
    .leftJoinAndSelect('therapist.languages', 'languages')
    .where('therapist.id = :therapistId', { therapistId })
    .getOne();

// "query 2":
const therapist_moreFieldsStringified = await this.therapistRepository.createQueryBuilder('therapist')
    .select([]) // otherwise will select therapist table columns
    .addSelect(qb => (
        qb.select(`JSON_ARRAYAGG(JSON_OBJECT("name", treatmentQualifications.name, "id", treatmentQualifications.id))`, "treatment_qualifications")
            .from("therapists_treatment_qualifications", "therapist_treatmentQualifications")
            .innerJoin("treatment_qualification", "treatmentQualifications", "treatmentQualifications.id = therapist_treatmentQualifications.treatment_qualification_id")
            .where("therapist_treatmentQualifications.user_id = therapist.id")
            .groupBy("therapist_treatmentQualifications.user_id")
    ), "treatmentQualifications")
... // more .addSelect(..^same as above^..) if needed

    .getRawOne();

// add fields of "query 2" to "query 1"`s therapist
for (const fieldName in therapist_moreFieldsStringified) {
    const stringifiedValue = therapist_moreFieldsStringified[fieldName]
    therapist[fieldName] = JSON.parse(stringifiedValue);
}

© www.soinside.com 2019 - 2024. All rights reserved.