1

これには 72 秒かかります。

SELECT distinct(meters.id)
FROM meters, meters_tags, houses_tags, tags
WHERE (
        tags.name = "xxx" AND ((
            meters_tags.tag_id = tags.id AND
            meters_tags.meter_id = meters.id
          ) OR (
            houses_tags.tag_id = tags.id AND
            houses_tags.house_id = meters.house_id
          )
        )
      );

これには 0.00 秒かかります。

SELECT distinct(meters.id)
FROM meters, meters_tags, houses_tags, tags
WHERE (
        tags.name = "xxx" AND ((
            meters_tags.tag_id = tags.id AND
            meters_tags.meter_id = meters.id
          )
        )
      );

これには 0.00 秒かかります。

SELECT distinct(meters.id)
FROM meters, meters_tags, houses_tags, tags
WHERE (
        tags.name = "xxx" AND ((
            houses_tags.tag_id = tags.id AND
            houses_tags.house_id = meters.house_id
          )
        )
      );

2 つのクエリのそれぞれに時間はかかりませんが、それらを OR すると 72 秒かかります。また、これを query0 AND ((query1) OR (query2)) の代わりに (query1) OR (query) の形式に変換しようとしましたが、これも非常に遅いです。

最初の(遅い)クエリの説明は次のとおりです。

+----+-------------+-------------+-------+----------------------------------------------------------------------------------------------------+------------------------------------------+---------+-------+-------+-------------------------------------------------------+
| id | select_type | table       | type  | possible_keys                                                                                      | key                                      | key_len | ref   | rows  | Extra                                                 |
+----+-------------+-------------+-------+----------------------------------------------------------------------------------------------------+------------------------------------------+---------+-------+-------+-------------------------------------------------------+
|  1 | SIMPLE      | meters_tags | index | index_meters_tags_on_tag_id_and_meter_id,index_meters_tags_on_tag_id,index_meters_tags_on_meter_id | index_meters_tags_on_tag_id_and_meter_id | 10      | NULL  |     1 | Using index; Using temporary                          |
|  1 | SIMPLE      | tags        | ref   | PRIMARY,tags_name                                                                                  | tags_name                                | 258     | const |     1 | Using where; Using index                              |
|  1 | SIMPLE      | meters      | index | PRIMARY,index_meters_on_house_id                                                                   | index_meters_on_house_id                 | 5       | NULL  | 45389 | Using index; Using join buffer                        |
|  1 | SIMPLE      | houses_tags | index | index_houses_tags_on_tag_id_and_house_id                                                           | index_houses_tags_on_tag_id_and_house_id | 10      | NULL  |  7158 | Using where; Using index; Distinct; Using join buffer |
+----+-------------+-------------+-------+----------------------------------------------------------------------------------------------------+------------------------------------------+---------+-------+-------+-------------------------------------------------------+

これらのテーブルはどれも 100k 行を超えません。これら 2 つのクエリを個別に実行すると非常に高速に実行できるのに、これら 2 つのクエリをマージするのに非常に長い時間がかかる可能性があるのは何でしょうか? サブクエリだけでもかなり高速なので、必要なすべてのインデックスが存在するようです。

4

1 に答える 1

1

結合されたクエリをよく見てください。houses_tags と meter_tags の相互結合を計算し、重複を並べ替えて削除し、残りのクエリに結合します。どちらの部分クエリも、houses_tags または meter_tags のいずれかをすぐに削除し、その他のみを使用します。したがって、劇的な速度の違い。

アドバイス: 最新の結合構文を学習して使用してください。理由が他にない場合は、これらの病的なケースを認識できるようになるまで回避するのに役立つからです。

于 2013-03-22T15:39:53.150 に答える