1 つのテーブルlocations
と 4 つの同一のテーブルがあります: countries
、、、regions
provinces
cities
すべてのテーブルは InnoDB です
すべてのテーブルには、id
Primary、Non-Null、Unsigned Int、Auto-Increment の列があります
すべてのテーブルには、name
Non-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 countries
OKです。すべてのテーブルは引き続きキーを使用します。
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 provinces
OKです。すべてのテーブルは引き続きキーを使用します。
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 cities
OKです。すべてのテーブルは引き続きキーを使用します。
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_time
regions
編集:私が尋ねている理由:
リージョンで LEFT JOIN を使用したクエリには、約 350 ミリ秒かかります (期間: 10 ミリ秒、フェッチ: 340 ミリ秒)。
リージョンに対する INNER JOIN を使用したクエリには、約 550 ミリ秒かかります。(期間: 330ms、フェッチ: 220ms)。
(正確にはわかりませんが、これはキャッシュできないことに関係していると思いますか?!)
編集2:
領域に対する STRAIGHT_JOIN を使用したクエリは、LEFT JOIN と同じように機能し、INNER JOIN と同じ出力を提供します。これはいい。regions
しかし、それでもテーブルの動作が異なる理由については答えられません。regions
と他の 3 つの一見同一のテーブルの実際の違いを見つけるには、どこを見ればよいでしょうか。