2

私の理解では、(My)SQL では、 aはすべての列でSELECT DISTINCTa と同じことを行う必要がありますが、暗黙的な並べ替えを行うため、これら 2 つのクエリは同じである必要があります。GROUP BYGROUP BY

SELECT boardID,threadID FROM posts GROUP BY boardID,threadID ORDER BY NULL LIMIT 100;
SELECT DISTINCT boardID,threadID FROM posts LIMIT 100;

どちらも同じ結果が得られ、次から同じ出力が得られますEXPLAIN

+----+-------------+-------+------+---------------+------+---------+------+---------+-----------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows    | Extra           |
+----+-------------+-------+------+---------------+------+---------+------+---------+-----------------+
|  1 | SIMPLE      | posts | ALL  | NULL          | NULL | NULL    | NULL | 1263320 | Using temporary |
+----+-------------+-------+------+---------------+------+---------+------+---------+-----------------+
1 row in set

しかし、私のテーブルでは、クエリはDISTINCT一貫して即座に返され、クエリGROUP BYは約 4 秒かかります。これをテストするために、クエリ キャッシュを無効にしました。

25 の列があるため、boardID 列と threadID 列のみを含む別のテーブルも作成しようとしましたが、同じ問題とパフォーマンスの違いが続きます。

の評価に含めずに追加の列を含めることができるように、代わりにを使用する必要あります。だから今、私はどのように進めるかはわかりません。なぜ違いがあるのですか?GROUP BYDISTINCTDISTINCT

4

1 に答える 1

3

まず第一に、クエリはまったく同じではありません。GROUP BY には ORDER BY がありますが、DISTINCT にはありません。

どちらの場合も、インデックスは使用されないため、パフォーマンスが向上しないことに注意してください。

複合インデックスを作成することをお勧めします(boardid, threadid)-これにより、両方のクエリでインデックスを使用できるようになり、両方がはるかに高速に動作し始めるはずです

編集:インデックスがない場合SELECT DISTINCT ... LIMIT 100よりも高速な理由の説明。GROUP BY ... LIMIT 100

最初のステートメント ( SELECT DISTINCT) を実行するには、サーバーは 100 行、おそらくそれより少し多い行をフェッチするだけで済み、100 行になるとすぐに停止できます。これ以上の作業は必要ありません。これは、元の SQL ステートメントで順序が指定されていないためです。そのため、サーバーは任意の 100 行を、それらが異なる限り配信できます。ORDER BYただし、この前にインデックスレスを課すLIMIT 100と、このクエリはすぐに遅くなります。

2 番目のステートメント ( SELECT ... GROUP BY ... LIMIT 100) を実行するために、MySQL は常にORDER BYGROUP BY で使用されたものと同じ列を暗黙的に実行します。つまり、すべてのレコードがフェッチされ、グループ化され、ソートされるまで、最初の数 100 行以上をフェッチした後、すぐに停止することはできません。その後、ORDER BY NULL追加したものを適用し(これはあまり効果がないと思いますが、削除すると速度が向上する可能性があります)、最後に最初の100行を取得し、残りの結果を破棄します。そしてもちろん、これは非常に遅いです。

複合インデックスを使用すると、これらすべての手順をいずれの場合でも非常に迅速に実行できます。

于 2012-11-13T05:11:18.563 に答える