优化具有连接的 MySQL 查询

Posted

技术标签:

【中文标题】优化具有连接的 MySQL 查询【英文标题】:Optimise MySQL query having joins 【发布时间】:2019-08-08 11:08:24 【问题描述】:

如何优化下面的查询。因为它有太多的连接

    SELECT `providers`.`provider_id`, `providers`.`providerFirstName`, `providers`.`providerLastName`, `providers`.`email`, `providers`.`phoneNumber`, `providers`.`address`, `providers`.`agencyName`, `providers`.`practiceCounty`, `providers`.`city`, `providers`.`state`, `providers`.`zip`, `providers`.`mondayHours`, `providers`.`tuesdayHours`, `providers`.`wednesdayHours`, `providers`.`thursdayHours`, `providers`.`fridayHours`, `providers`.`saturdayHours`, `providers`.`sundayHours`, `providers`.`additionalInfo`, `providers`.`website`, `providers`.`newClientsAcceptance`, `providers`.`updatedBy`, `providers`.`otherCategories`, `providers`.`otherInsurances`, `providers`.`otherTelehealthServices`, `providers`.`createdAt`, `providers`.`updatedAt`, `ProviderInsurances`.`provider_insurance_id` AS `ProviderInsurances.provider_insurance_id`, `ProviderInsurances`.`insurance_id` AS `ProviderInsurances.insurance_id`, `ProviderInsurances->Insurance`.`insurance_id` AS `ProviderInsurances.Insurance.insurance_id`, `ProviderInsurances->Insurance`.`insurance_name` AS `ProviderInsurances.Insurance.insurance_name`, `ProviderClients`.`provider_client_id` AS `ProviderClients.provider_client_id`, `ProviderClients`.`client_id` AS `ProviderClients.client_id`, `ProviderClients->Client`.`client_id` AS `ProviderClients.Client.client_id`, `ProviderClients->Client`.`client_name` AS `ProviderClients.Client.client_name`, `ProviderCounties`.`provider_county_id` AS `ProviderCounties.provider_county_id`, `ProviderCounties`.`county_id` AS `ProviderCounties.county_id`, `ProviderCounties->County`.`county_id` AS `ProviderCounties.County.county_id`, `ProviderCounties->County`.`county_name` AS `ProviderCounties.County.county_name`, `ProviderSpecialities`.`provider_speciality_id` AS `ProviderSpecialities.provider_speciality_id`, `ProviderSpecialities`.`speciality_id` AS `ProviderSpecialities.speciality_id`, `ProviderSpecialities->Speciality`.`speciality_id` AS `ProviderSpecialities.Speciality.speciality_id`, `ProviderSpecialities->Speciality`.`speciality_name` AS `ProviderSpecialities.Speciality.speciality_name`, `ProviderCategories`.`provider_category_id` AS `ProviderCategories.provider_category_id`, `ProviderCategories`.`category_id` AS `ProviderCategories.category_id`, `ProviderCategories->Category`.`category_id` AS `ProviderCategories.Category.category_id`, `ProviderCategories->Category`.`category_name` AS `ProviderCategories.Category.category_name`, `Telehealths`.`telehealth_id` AS `Telehealths.telehealth_id`, `Telehealths`.`telehealth_name` AS `Telehealths.telehealth_name` 
FROM `providers` AS `providers` 
LEFT OUTER JOIN `provider_insurances` AS `ProviderInsurances` ON `providers`.`provider_id` = `ProviderInsurances`.`provider_id` 
LEFT OUTER JOIN `insurance` AS `ProviderInsurances->Insurance` ON `ProviderInsurances`.`insurance_id` = `ProviderInsurances->Insurance`.`insurance_id` 
LEFT OUTER JOIN `provider_clients` AS `ProviderClients` ON `providers`.`provider_id` = `ProviderClients`.`provider_id` 
LEFT OUTER JOIN `clients` AS `ProviderClients->Client` ON `ProviderClients`.`client_id` = `ProviderClients->Client`.`client_id` 
LEFT OUTER JOIN `provider_counties` AS `ProviderCounties` ON `providers`.`provider_id` = `ProviderCounties`.`provider_id` 
LEFT OUTER JOIN `counties` AS `ProviderCounties->County` ON `ProviderCounties`.`county_id` = `ProviderCounties->County`.`county_id` 
LEFT OUTER JOIN `provider_specialities` AS `ProviderSpecialities` ON `providers`.`provider_id` = `ProviderSpecialities`.`provider_id` 
LEFT OUTER JOIN `specialities` AS `ProviderSpecialities->Speciality` ON `ProviderSpecialities`.`speciality_id` = `ProviderSpecialities->Speciality`.`speciality_id` 
LEFT OUTER JOIN `provider_categories` AS `ProviderCategories` ON `providers`.`provider_id` = `ProviderCategories`.`provider_id` 
LEFT OUTER JOIN `categories` AS `ProviderCategories->Category` ON `ProviderCategories`.`category_id` = `ProviderCategories->Category`.`category_id` 
LEFT OUTER JOIN `telehealth` AS `Telehealths` ON `providers`.`provider_id` = `Telehealths`.`provider_id` 
WHERE `providers`.`updatedAt` 
BETWEEN '2019-08-06 18:30:00' AND '2019-08-08 00:00:00';

减少执行时间的最佳做法是什么。请帮忙。

我在下面添加了“EXPLAIN SELECT”输出

【问题讨论】:

请提供EXPLAIN SELECT ... @RickJames 我已经添加了上面的截图 请不要对EXPLAIN的行进行排序;行的顺序是关键信息。 请提供SHOW CREATE TABLE provider_counties 【参考方案1】:

确保您对连接所涉及的列有正确的索引,例如:

table  provider_insurances columns  (provider_id, insurance_id)
table  insurance columns (insurance_id)
table  provider_clients columns (provider_id)
...
....
table  providers columns (updatedAt, provider_id )

【讨论】:

是的,我已经为 updatedAt 添加了普通索引,并为上面所有剩余的列添加了主键索引。但执行时间仍然相同 还有另一列不仅涉及主键..所以检查你是否有建议的索引.. @rjirji 为了澄清 scaisEdge 已经发布的答案,您有 11 个外连接指定要连接的列(ON providers.provider_id = ProviderInsurances.provider_id)。您必须确保这 22 列中的每一列都已编入索引。此外,应为 Where 子句中的所有列编制索引以获得更好的性能。 @James 主键是索引吗?所有 22 列都被赋予主键,where 子句中的列被赋予自定义索引。够了吗? @rjirji - 是的 PRIMARY KEY 在索引中。 (它是一个UNIQUE 索引。)【参考方案2】:

您可以使用 sequelize ORM 来处理您的查询连接。链接 => [https://sequelize.org/master/manual/querying.html]

【讨论】:

不是续集。我在问如何优化执行时间 这不是答案。

以上是关于优化具有连接的 MySQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

优化多个 MySQL 视图的连接

具有多个分组或排序的mysql查询优化

MySQL 查询优化 - 子查询 + 多连接

优化具有大量数据的MYSQL查询

带有连接和子查询的 mysql 查询优化

具有 JOIN 和 GROUP BY 优化的 MySQL 查询。是不是可以?