[英]Optimizing MySQL Left join query between 3 tables to reduce execution time
我有以下查詢:
SELECT region.id, region.world_id, min_x, min_y, min_z, max_x, max_y, max_z, version, mint_version
FROM minecraft_worldguard.region
LEFT JOIN minecraft_worldguard.region_cuboid
ON region.id = region_cuboid.region_id
AND region.world_id = region_cuboid.world_id
LEFT JOIN minecraft_srvr.lot_version
ON id=lot
WHERE region.world_id = 10
AND region_cuboid.world_id=10;
Mysql慢速查詢日志告訴我,執行需要5秒鍾以上的時間,返回2300行,但檢查15'404'545行以返回它。
這三個表各有6500行,只有id和lot字段上的唯一鍵以及world_id字段上的鍵。 我試圖通過根據長方體和世界的ID以及world_id上的雙WHERE來過濾長方體和世界,以盡量減少檢查的行數,但這似乎無濟於事。
知道如何優化此查詢嗎?
這是帶有當前狀態索引的sqlfiddle 。
您已將兩個表“ minecraft_worldguard.region”和“ minecraft_worldguard.region_cuboid”加入到region.world_id和region_cuboid.world_id上。 因此,WHERE子句不需要兩個條件。
WHERE子句中的兩列已等於JOIN條件,因此您無需檢查WHERE子句中的兩個條件。 在WHERE子句中刪除其中之一,並在保留WHERE條件的列上添加索引。
在您的示例中,保留WHERE子句如下:WHERE region.world_id = 10
並在region.world_id列上添加索引,這將提高性能。
注意:請注意,我建議您丟棄“ AND region_cuboid.world_id = 10;”。 WHERE子句的一部分。
希望能有所幫助。
首先,編寫具有多個表的查詢時,習慣於“別名”對表的引用是一件非常好的事情,這樣您就不必在整個過程中都重新輸入整個長名。 同樣,確定列來自哪些表是一個非常好的主意,以使用戶更好地了解哪些地方可以幫助提高性能(例如建議覆蓋索引)。
就是說,我已經對您的原始查詢應用了別名,但是會按相應列對表進行猜測,但是顯然您可以快速識別並進行調整。
SELECT
R.id,
R.world_id,
RC.min_x,
RC.min_y,
RC.min_z,
RC.max_x,
RC.max_y,
RC.max_z,
LV.version,
LV.mint_version
FROM
minecraft_worldguard.region R
LEFT JOIN minecraft_worldguard.region_cuboid RC
ON R.id = RC.region_id
AND R.world_id = RC.world_id
LEFT JOIN minecraft_srvr.lot_version LV
ON R.id = LV.lot
WHERE
R.world_id = 10
我還從where子句中刪除了您的“ region_cuboid.world_id = 10”,這是由於基於區域AND world的JOIN子句的結果是多余的。
為了建議索引,並且如果我對列有適當的別名引用,我建議在(world_id,id)的區域表上建議覆蓋索引。 第一個位置的“ World_id”很快使WHERE子句合格,並且RC和LV表的“ id”在那里。
對於region_cuboid表,我還要在(world_id,region_id)上有一個索引,以匹配要加入該表的區域表。
對於lot_version表,在(批次)上具有索引,或在(批次,版本,mint_version)上具有覆蓋索引
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.