1 つのテーブルlocationsと 4 つの同一のテーブルがあります: countries、、、regionsprovincescities
すべてのテーブルは InnoDB です
すべてのテーブルには、idPrimary、Non-Null、Unsigned Int、Auto-Increment の列があります
すべてのテーブルには、nameNon-Null、VarChar、デフォルトの列があります ''
locations他の 4 つのテーブルすべてへの外部キーを保持します。すべて非 Null。
テーブルには、他のlocationsいくつかの列とインデックス/キーも保持されますが、他の 4 つのテーブルに関連するものはありません
今、私はこのクエリを持っています:
DESCRIBE SELECT * FROM locations
LEFT JOIN cities ON locations.city_id = cities.id
LEFT JOIN provinces ON locations.province_id = provinces.id
LEFT JOIN regions ON locations.region_id = regions.id
LEFT JOIN countries ON locations.country_id = countries.id
WHERE locations.id > 1
結果は満足のいくものです。すべてのテーブルがそれぞれのキーを使用します。
1, SIMPLE, locations, range , PRIMARY, PRIMARY, 4, , 393, Using where
1, SIMPLE, cities , eq_ref, PRIMARY, PRIMARY, 4, mydb.locations.city_id , 1,
1, SIMPLE, provinces, eq_ref, PRIMARY, PRIMARY, 4, mydb.locations.province_id, 1,
1, SIMPLE, regions , eq_ref, PRIMARY, PRIMARY, 4, mydb.locations.region_id , 1,
1, SIMPLE, countries, eq_ref, PRIMARY, PRIMARY, 4, mydb.locations.country_id , 1,
質問:
に変更するだけLEFT JOIN countriesでINNER JOIN countriesOKです。すべてのテーブルは引き続きキーを使用します。
1, SIMPLE, locations, range , PRIMARY,locations_country_id_fk, PRIMARY, 4, , 341, Using where
1, SIMPLE, cities , eq_ref, PRIMARY , PRIMARY, 4, ftc_dev.locations.city_id , 1,
1, SIMPLE, provinces, eq_ref, PRIMARY , PRIMARY, 4, ftc_dev.locations.province_id, 1,
1, SIMPLE, regions , eq_ref, PRIMARY , PRIMARY, 4, ftc_dev.locations.region_id , 1,
1, SIMPLE, countries, eq_ref, PRIMARY , PRIMARY, 4, ftc_dev.locations.country_id , 1,
に変更するだけLEFT JOIN provincesでINNER JOIN provincesOKです。すべてのテーブルは引き続きキーを使用します。
1, SIMPLE, locations, range , PRIMARY,locations_province_id_fk, PRIMARY, 4, , 341, Using where
1, SIMPLE, provinces, eq_ref, PRIMARY , PRIMARY, 4, ftc_dev.locations.province_id, 1,
1, SIMPLE, regions , eq_ref, PRIMARY , PRIMARY, 4, ftc_dev.locations.region_id , 1,
1, SIMPLE, countries, eq_ref, PRIMARY , PRIMARY, 4, ftc_dev.locations.country_id , 1,
1, SIMPLE, cities , eq_ref, PRIMARY , PRIMARY, 4, ftc_dev.locations.city_id , 1,
に変更するだけLEFT JOIN citiesでINNER JOIN citiesOKです。すべてのテーブルは引き続きキーを使用します。
1, SIMPLE, locations, range , PRIMARY,locations_city_id_fk, PRIMARY, 4, , 341, Using where
1, SIMPLE, provinces, eq_ref, PRIMARY , PRIMARY, 4, ftc_dev.locations.province_id, 1,
1, SIMPLE, regions , eq_ref, PRIMARY , PRIMARY, 4, ftc_dev.locations.region_id , 1,
1, SIMPLE, countries, eq_ref, PRIMARY , PRIMARY, 4, ftc_dev.locations.country_id , 1,
1, SIMPLE, cities , eq_ref, PRIMARY , PRIMARY, 4, ftc_dev.locations.city_id , 1,
ただし、にだけ変更LEFT JOIN regionsしても問題INNER JOIN regionsありません。テーブルはそのregionsキーを使用しません。私はこれを得る:
1, SIMPLE, regions , ALL , PRIMARY , null , null, null , 269,
1, SIMPLE, locations, ref , PRIMARY,locations_region_id_fk, locations_region_id_fk, 5, mydb.regions.id , 1, Using where
1, SIMPLE, cities , eq_ref, PRIMARY , PRIMARY , 4, mydb.locations.city_id , 1,
1, SIMPLE, provinces, eq_ref, PRIMARY , PRIMARY , 4, mydb.locations.province_id, 1,
1, SIMPLE, countries, eq_ref, PRIMARY , PRIMARY , 4, mydb.locations.country_id , 1,
これは奇妙です!なぜならcountries、、、、私が見る限り同一だからregionsですprovinces!citiesしかし、この動作は、4 つのテーブルが(テーブルに対して) 同一ではないlocationsことを証明しています。それらをより同一にするために、何を見逃した可能性がありますか?
私はすでに と を見てきましSHOW TABLE STATUS LIKE 'table_name'たDESCRIBE table_name。ほとんどすべてが同じです。また、変更がある場合 (例: rows、avg_row_length、data_length、)、auto_increment表の値は常に他の値の中間にあります。create_timeregions
編集:私が尋ねている理由:
リージョンで LEFT JOIN を使用したクエリには、約 350 ミリ秒かかります (期間: 10 ミリ秒、フェッチ: 340 ミリ秒)。
リージョンに対する INNER JOIN を使用したクエリには、約 550 ミリ秒かかります。(期間: 330ms、フェッチ: 220ms)。
(正確にはわかりませんが、これはキャッシュできないことに関係していると思いますか?!)
編集2:
領域に対する STRAIGHT_JOIN を使用したクエリは、LEFT JOIN と同じように機能し、INNER JOIN と同じ出力を提供します。これはいい。regionsしかし、それでもテーブルの動作が異なる理由については答えられません。regionsと他の 3 つの一見同一のテーブルの実際の違いを見つけるには、どこを見ればよいでしょうか。