我正在运行一个查询,并且正在努力理解MySQL为什么这么慢地运行它。我在下面的3个场景中包含了实际查询和EXPLAIN。
第一个查询运行速度非常慢(23秒),但从where子句中只删除一个字段(查询2)会导致查询在0.010秒内运行。这是一个TinyInt字段(基本上存储了布尔值0/1)。
项目 - > hasMany - >里程碑 - > hasMany - >任务
task_wishlist是任务和愿望清单之间的数据透视表
QUERY 1
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="INSTALLFOLDER" Name="DataBaseds_Service_Installer" />
</Directory>
</Directory>
<ComponentGroup Id="Components" Directory="INSTALLFOLDER">
...some components
</ComponentGroup>
<DirectoryRef Id="TARGETDIR">
<Component Id="MYSQL_PASSWORD" Guid="..."
<Environment Id=HERE YOU CAN ADD THIS :)/>
</Component>
</DirectoryRef>
查询1 EXPLAIN:
SELECT `tasks`.*,
task_wishlist.description AS item_description,
task_wishlist.created_at AS item_created_at
FROM `tasks`
LEFT JOIN `task_wishlist` ON `tasks`.`id` = `task_wishlist`.`task_id`
LEFT JOIN `milestones` ON `tasks`.`milestone_id` = `milestones`.`id`
LEFT JOIN `projects` ON `milestones`.`project_id` = `projects`.`id`
WHERE `task_wishlist`.`wishlist_id` = '527021'
AND `tasks`.`active` = '1'
AND `projects`.`active` = '1'
AND `milestones`.`active` = '1'
ORDER BY `task_wishlist`.`created_at` DESC
LIMIT 25;
/* Affected rows: 0 Found rows: 25 Warnings: 0 Duration for 1 query: 23.072 sec. (+ 0.040 sec. network) */
查询2(删除里程碑。活动)
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: projects
partitions: NULL
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 997
filtered: 10.00
Extra: Using where; Using temporary; Using filesort
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: milestones
partitions: NULL
type: ref
possible_keys: PRIMARY,milestones_project_id_foreign
key: milestones_project_id_foreign
key_len: 4
ref: fusion.projects.id
rows: 3
filtered: 10.00
Extra: Using index condition; Using where
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: tasks
partitions: NULL
type: ref
possible_keys: PRIMARY,tasks_milestone_id_foreign
key: tasks_milestone_id_foreign
key_len: 5
ref: fusion.milestones.id
rows: 5
filtered: 10.00
Extra: Using where
*************************** 4. row ***************************
id: 1
select_type: SIMPLE
table: task_wishlist
partitions: NULL
type: ref
possible_keys: task_wishlist_wishlist_id_foreign,task_wishlist_task_id_foreign
key: task_wishlist_task_id_foreign
key_len: 4
ref: fusion.tasks.id
rows: 100
filtered: 0.28
Extra: Using where
4 rows in set, 1 warning (0.01 sec)
查询2解释:
SELECT `tasks`.*,
task_wishlist.description AS item_description,
task_wishlist.created_at AS item_created_at
FROM `tasks`
LEFT JOIN `task_wishlist` ON `tasks`.`id` = `task_wishlist`.`task_id`
LEFT JOIN `milestones` ON `tasks`.`milestone_id` = `milestones`.`id`
LEFT JOIN `projects` ON `milestones`.`project_id` = `projects`.`id`
WHERE `task_wishlist`.`wishlist_id` = '527021'
AND `tasks`.`active` = '1'
AND `projects`.`active` = '1'
/*AND `milestones`.`active` = '1'*/
ORDER BY `task_wishlist`.`created_at` DESC
LIMIT 25;
/* Affected rows: 0 Found rows: 25 Warnings: 0 Duration for 1 query: 0.028 sec. (+ 0.010 sec. network) */
查询3:删除projects.active = 1
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: task_wishlist
partitions: NULL
type: ref
possible_keys: task_wishlist_wishlist_id_foreign,task_wishlist_task_id_foreign
key: task_wishlist_wishlist_id_foreign
key_len: 4
ref: const
rows: 7224
filtered: 100.00
Extra: Using index condition; Using where; Using filesort
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: tasks
partitions: NULL
type: eq_ref
possible_keys: PRIMARY,tasks_milestone_id_foreign
key: PRIMARY
key_len: 4
ref: fusion.task_wishlist.task_id
rows: 1
filtered: 10.00
Extra: Using where
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: milestones
partitions: NULL
type: eq_ref
possible_keys: PRIMARY,milestones_project_id_foreign
key: PRIMARY
key_len: 4
ref: fusion.tasks.milestone_id
rows: 1
filtered: 100.00
Extra: NULL
*************************** 4. row ***************************
id: 1
select_type: SIMPLE
table: projects
partitions: NULL
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: fusion.milestones.project_id
rows: 1
filtered: 10.00
Extra: Using where
4 rows in set, 1 warning (0.00 sec)
查询3解释
SELECT `tasks`.*,
task_wishlist.description AS item_description,
task_wishlist.created_at AS item_created_at
FROM `tasks`
LEFT JOIN `task_wishlist` ON `tasks`.`id` = `task_wishlist`.`task_id`
LEFT JOIN `milestones` ON `tasks`.`milestone_id` = `milestones`.`id`
LEFT JOIN `projects` ON `milestones`.`project_id` = `projects`.`id`
WHERE `task_wishlist`.`wishlist_id` = '527021'
AND `tasks`.`active` = '1'
/*AND `projects`.`active` = '1'*/
AND `milestones`.`active` = '1'
ORDER BY `task_wishlist`.`created_at` DESC
LIMIT 25;
/* Affected rows: 0 Found rows: 25 Warnings: 0 Duration for 1 query: 0.027 sec. (+ 4.031 sec. network) */
如何使此查询在包含所有*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: task_wishlist
partitions: NULL
type: ref
possible_keys: task_wishlist_wishlist_id_foreign,task_wishlist_task_id_foreign
key: task_wishlist_wishlist_id_foreign
key_len: 4
ref: const
rows: 7224
filtered: 100.00
Extra: Using index condition; Using where; Using filesort
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: tasks
partitions: NULL
type: eq_ref
possible_keys: PRIMARY,tasks_milestone_id_foreign
key: PRIMARY
key_len: 4
ref: fusion.task_wishlist.task_id
rows: 1
filtered: 10.00
Extra: Using where
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: milestones
partitions: NULL
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: fusion.tasks.milestone_id
rows: 1
filtered: 10.00
Extra: Using where
*************************** 4. row ***************************
id: 1
select_type: SIMPLE
table: projects
partitions: NULL
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: fusion.milestones.project_id
rows: 1
filtered: 100.00
Extra: Using index
4 rows in set, 1 warning (0.00 sec)
字段的情况下正常运行?
答案 0 :(得分:2)
您需要重申的一个事实是,您的查询实际上是在做简单的INNER JOIN而不是LEFT JOINS。
如果join-condition在&#34; right&#34;中没有找到任何匹配的行,Left outer join基本上与内连接exept一样工作,它返回NULL。表。
但是查询中的所有NULL都会被WHERE子句中的条件过滤掉,请仔细检查查询:
FROM `tasks`
LEFT JOIN `task_wishlist` ON `tasks`.`id` = `task_wishlist`.`task_id`
LEFT JOIN `milestones` ON `tasks`.`milestone_id` = `milestones`.`id`
LEFT JOIN `projects` ON `milestones`.`project_id` = `projects`.`id`
WHERE `task_wishlist`.`wishlist_id` = '527021'
AND `tasks`.`active` = '1'
AND `milestones`.`active` = '1'
AND `projects`.`active` = '1'
LEFT JOIN task_wishlist
的WHERE task_wishlist.wishlist_id = '527021'
LEFT JOIN milestones
的WHERE milestones.active = '1'
LEFT JOIN projects
的WHERE projects.active = '1'
MySql知道这一点,并在内部将您的查询重写为INNER JOIN查询:
FROM `tasks`
INNER JOIN `task_wishlist` ON `tasks`.`id` = `task_wishlist`.`task_id`
INNER JOIN `milestones` ON `tasks`.`milestone_id` = `milestones`.`id`
INNER JOIN `projects` ON `milestones`.`project_id` = `projects`.`id`
WHERE `task_wishlist`.`wishlist_id` = '527021'
AND `tasks`.`active` = '1'
AND `milestones`.`active` = '1'
AND `projects`.`active` = '1'
如果从WHERE子句中删除(注释)某些条件,则此&#34;激活&#34;对应的LEFT JOIN是查询的一部分,因此查询的语义发生了变化,它的结果集也发生了变化。比较这些查询的性能没有任何意义,因为它们坦率地不同,事实上你正在将苹果与橙子进行比较。
由于查询正在执行简单的INNER JOIN,您可以将其重写为:
FROM `tasks`
INNER JOIN `task_wishlist` ON `tasks`.`id` = `task_wishlist`.`task_id`
AND `task_wishlist`.`wishlist_id` = '527021'
INNER JOIN `milestones` ON `tasks`.`milestone_id` = `milestones`.`id`
AND `milestones`.`active` = '1'
INNER JOIN `projects` ON `milestones`.`project_id` = `projects`.`id`
AND `projects`.`active` = '1'
现在在上面的条件中你可以很容易地看到&#34;对&#34;在连接期间使用的列:
尝试在那里添加多个索引&#34;对&#34;,projects
表的一个示例:
CREATE INDEX xxx ON projects( id, active )
如果id
列也是主键,则可能只能在单active
列而不是多列(id, active)
添加索引,因为in InnoDB, each record in a secondary index contains the primary key columns for the row, as well as the columns specified for the secondary index.
你必须自己试验。
答案 1 :(得分:1)
您说task_wishlist
是tasks
和wishlists
之间的多对多映射表吗?我敢打赌它没有像样的指数。按照这里的提示:
http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table
如果这还不够,那么请为每个表返回SHOW CREATE TABLE
。