早上好。
有人可以向我解释,为什么在MySQL中,如果我将成为INNER JOINS
并在WHERE
clouse中从一个连接表中的索引列中添加简单条件,则首先执行连接,然后执行扫描中间结果提供的条件?
我认为,优化查询应首先从where子句中包含的表中选择适当的行,然后执行正确的连接,因为这会减少表读取错误?目前的行为对我来说只是愚蠢的。此类行为的示例如下。
explain select
patent0_.id as id1_6_0_,
referencen1_.id as id1_7_1_,
service2_.id as id1_8_2_,
applicant3_.id as id1_0_3_,
country4_.id as id1_2_4_,
patent0_.applicant_id as applica14_6_0_,
patent0_.applicationDate as applicat2_6_0_,
patent0_.applicationLanguage as applicat3_6_0_,
patent0_.applicationNumber as applicat4_6_0_,
patent0_.classification as classifi5_6_0_,
patent0_.creationDate as creation6_6_0_,
patent0_.disabled as disabled7_6_0_,
patent0_.licenceInfo as licenceI8_6_0_,
patent0_.patentName as patentNa9_6_0_,
patent0_.publicationDate as publica10_6_0_,
patent0_.publicationNumber as publica11_6_0_,
patent0_.registrationDate as registr12_6_0_,
patent0_.registrationNumber as registr13_6_0_,
referencen1_.creationDate as creation2_7_1_,
referencen1_.design_id as design_i8_7_1_,
referencen1_.error as error3_7_1_,
referencen1_.hasRenewal as hasRenew4_7_1_,
referencen1_.info as info5_7_1_,
referencen1_.patent_id as patent_i9_7_1_,
referencen1_.referenceNumber as referenc6_7_1_,
referencen1_.service_id as service10_7_1_,
referencen1_.trademark_id as tradema11_7_1_,
referencen1_.type as type7_7_1_,
service2_.additional_name as addition2_8_2_,
service2_.name as name3_8_2_,
applicant3_.address as address2_0_3_,
applicant3_.addressSource_id as address13_0_3_,
applicant3_.city as city3_0_3_,
applicant3_.country_id as country14_0_3_,
applicant3_.createdDate as createdD4_0_3_,
applicant3_.deleted as deleted5_0_3_,
applicant3_.disabled as disabled6_0_3_,
applicant3_.entryCount as entryCou7_0_3_,
applicant3_.entryCountChanged as entryCou8_0_3_,
applicant3_.manualModified as manualMo9_0_3_,
applicant3_.modifiedDate as modifie10_0_3_,
applicant3_.name as name11_0_3_,
applicant3_.zipCode as zipCode12_0_3_,
country4_.dateFormat as dateForm2_2_4_,
country4_.englishName as englishN3_2_4_,
country4_.iso3166 as iso4_2_4_,
country4_.locale as locale5_2_4_,
country4_.name as name6_2_4_,
country4_.polishName as polishNa7_2_4_
from
patent patent0_
inner join
referencenumber referencen1_ ON patent0_.id = referencen1_.patent_id
inner join
service service2_ ON referencen1_.service_id = service2_.id
inner join
applicant applicant3_ ON patent0_.applicant_id = applicant3_.id
inner join
country country4_ ON applicant3_.country_id = country4_.id
where
patent0_.applicant_id = 102014
解释结果:
+----+-------------+--------------+--------+-----------------------------------------------------------------------+------------------------------+---------+-----------------------------------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+--------+-----------------------------------------------------------------------+------------------------------+---------+-----------------------------------+-------+-------------+
| 1 | SIMPLE | applicant3_ | const | PRIMARY,FK_cjteymxk1h6sce00e4vtar8we | PRIMARY | 4 | const | 1 | NULL |
| 1 | SIMPLE | country4_ | const | PRIMARY | PRIMARY | 4 | const | 1 | NULL |
| 1 | SIMPLE | service2_ | ALL | PRIMARY | NULL | NULL | NULL | 27 | NULL |
| 1 | SIMPLE | referencen1_ | ref | patent_id_UNIQUE,FK_fcy9m21m0jaid4l8e8bbsms1v,FK_5lMjxN8AZfRUOuCWebvP | FK_fcy9m21m0jaid4l8e8bbsms1v | 5 | trademarks.service2_.id | 60454 | Using where |
| 1 | SIMPLE | patent0_ | eq_ref | PRIMARY,FK_8991d6757d10418eaa7cd8fe1da | PRIMARY | 4 | trademarks.referencen1_.patent_id | 1 | Using where |
+----+-------------+--------------+--------+-----------------------------------------------------------------------+------------------------------+---------+-----------------------------------+-------+-------------+
我当时希望此查询首先使用正确的applicant_id获取所有专利,然后在该行上执行INNER JOINS
。为了实现这一点,我必须将所有内部关节改为左连接。
那么为什么INNER JOINS
有这么糟糕的优化路径呢?如何解决?
根据要求,此处是LEFT JOINS
INNER JOINS
+----+-------------+--------------+--------+------------------------------------------+--------------------------------+---------+------------------------------------+---------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------------+--------+------------------------------------------+--------------------------------+---------+------------------------------------+---------+-------+
| 1 | SIMPLE | patent0_ | ref | FK_8991d6757d10418eaa7cd8fe1da | FK_8991d6757d10418eaa7cd8fe1da | 5 | const | 86 | NULL |
| 1 | SIMPLE | referencen1_ | ref | patent_id_UNIQUE,FK_5lMjxN8AZfRUOuCWebvP | patent_id_UNIQUE | 5 | trademarks.patent0_.id | 1632272 | NULL |
| 1 | SIMPLE | service2_ | eq_ref | PRIMARY | PRIMARY | 4 | trademarks.referencen1_.service_id | 1 | NULL |
| 1 | SIMPLE | applicant3_ | const | PRIMARY | PRIMARY | 4 | const | 1 | NULL |
| 1 | SIMPLE | country4_ | eq_ref | PRIMARY | PRIMARY | 4 | trademarks.applicant3_.country_id | 1 | NULL |
+----+-------------+--------------+--------+------------------------------------------+--------------------------------+---------+------------------------------------+---------+-------+
的同一查询的执行计划
{{1}}