2

この wiki 記事を読んで、MySQL データベースでインデックス付きの列で IN() 句を使用すると、SELECT のパフォーマンスが低下することがわかりました。私の質問は、機能を維持しながら IN() 句を使用しないようにクエリを書き直すにはどうすればよいですか?

私のクエリは次のとおりです。

SELECT 
    `Route`.`route_id`, `Route`.`order`, `Route2`.`order` 
FROM 
    `routes` AS `Route` 
INNER JOIN 
    `routes` AS `Route2` 
ON `Route`.`route_id` = `Route2`.`route_id` 
WHERE 
    `Route`.`station_line_id` IN ([10 values]) AND 
    `Route2`.`station_line_id` IN ([10 values]) AND 
    `Route`.`order` <= `Route2`.`order` 
GROUP BY `
    `Route`.`station_line_id`, `Route2`.`station_line_id`, (`Route2`.`order` - `Route`.`order`)

そして、すべての列 (route_id、station_line_id、station_id、line_id) にインデックスを付けました。id 列は主キーです (テーブルは一度生成されると読み取り専用なので、すべてにインデックスを付ける心配はありません)。IN() 句の[10 values]は、次のようにカンマで区切られていますIN(1, 2, ..., 10)

基本的に、自分でテーブル ルート テーブルに参加し、結果をグループ化して目的のレコードを取得します。他の結合は、関連データを取得するために使用されます。

パフォーマンスに関しては、InnoDB ストレージ エンジンを使用して、同様のクエリを 30 秒以上で実行しました。MyISAM を使用すると、5 秒以上かかります。しかし、結果はさらに速く取得できると思います。テーブルには最大 450 万件のレコードがあります。

4

1 に答える 1

1

「ハッシュ インデックス」を使用すると、このようなクエリで最高のパフォーマンスが得られます。「標準」インデックスは B+ ツリーであり、log(n) 時間 (n はテーブル内の行数) でエントリを検索できます。また、ソートされた順序を維持するため、... WHERE station_line_id > 14のようなクエリを効率的に実行できるため、列で使用する必要がありますOrder

ただし、あなたの場合、IN節を使用すると、同等性のみを探しています。その場合、B+ ツリーは m 個すべての "[10 値]" を個別に検索する必要があり、m * log(n) 時間がかかります。これには明らかに 5 ~ 30 秒かかります。

ハッシュ インデックスは、テーブル内の行数に (理論的には) 依存しない一定時間 (非常に高速) で同等のエントリを検索するために使用されます。大きなテーブルでも常に非常に高速です。<ハッシュ インデックスの欠点は、やのようなクエリを実行するために使用できないことですが、 の句で>実行しているような等価クエリでは最速です。INstation_line_id

編集:特にMySQLの場合、残念ながら、人気のあるデータベースエンジンのいずれでもHASHインデックスをサポートしていません. MEMORY または HEAP エンジンを使用できる場合は、HASH インデックスを使用できます。すべてをメモリに格納すると、パフォーマンスがかなり向上する可能性があります。試してみる価値。

于 2012-04-13T15:30:49.377 に答える