5

昨日、サーバー上で遅いクエリが実行されているのを見つけました (このクエリは 1 分以上かかります)。次のようになります。

select a.* from a 
left join b on a.hotel_id=b.hotel_id and a.hotel_type=b.hotel_type
where b.hotel_id is null

テーブル a には 40000 行以上、テーブル b には 10000 行以上あります。 テーブル b の hotel_id 列と hotel_type 列には UNIQUE KEY idx_hotel_id( hotel_id, hotel_type) のように一意のキーが既に作成されています。このSQLと私は次のような結果を得ました:

                type            key                             rows
1   SIMPLE  a   ALL     NULL    NULL            NULL    NULL    36804   
1   SIMPLE  b   index   NULL    idx_hotel_id    185     NULL    8353    Using where; Using index; Not exists

MySQL のリファレンス マニュアルによると、インデックスのすべての部分が結合によって使用され、インデックスが PRIMARY KEY または UNIQUE NOT NULL インデックスである場合、結合タイプは「eq_ref」になります。クエリ プランの 2 行目を参照してください。列タイプの値は「index」です。しかし、実際には hotel_id と hotel_type に一意のインデックスがあり、2 つの列の両方が結合で使用されていました。結合タイプ「ef_ref」は、結合タイプ「ref」と「ref」よりも効率的です。 " は "range" よりも効率的です。"index" は、"ALL" を除く最後の結合タイプです。これが私が混乱していることであり、ここでの結合タイプが "index" である理由を知りたいです。私の質問を明確に説明したいと思います。皆さんからの回答を楽しみにしています。ありがとう!

4

2 に答える 2

1

Where Is Null チェックは遅くなる可能性があるため、おそらくそれが原因です。

select * from a 
where not exists ( select 1 from b where a.hotel_id=b.hotel_id and a.hotel_type=b.hotel_type )

また、何件のレコードを返しますか? すべての 36804 レコードを返す場合、これも速度が低下する可能性があります。

于 2013-11-14T07:34:45.387 に答える
0

上記のすべての人に感謝します!私は自分の問題を自分で解決する方法を見つけました.hotel_id列とhotel_type列に同じ文字セットがありません.両方を「utf8」にした後、クエリは約10ミリ秒未満で結果を返しました. MySQL の左結合とインデックスに関する優れた記事があります。皆さんに強くお勧めします。サイトは次のとおりです。 vs-left-join-is-null-mysql/

于 2013-11-17T16:10:15.093 に答える