P粉9738995672023-08-21 11:26:01
UPD: 2017-03-31、MySQL バージョン 5.7.5 では、ONLY_FULL_GROUP_BY スイッチがデフォルトで有効になっています (したがって、非決定的な GROUP BY クエリは無効になっています)。さらに、GROUP BY 実装が更新されたため、スイッチが無効になっていてもソリューションが期待どおりに動作しなくなる可能性があります。検査が必要です。
Bill Karwin のソリューションは、グループ内の項目数が少ない場合にはうまく機能しますが、グループが大きくなると、ソリューションに約 n*n/2 n/2## かかるため、クエリのパフォーマンスが低下します。 #times
IS NULL比較。
行と 1182
グループを含む InnoDB テーブルでテストしました。このテーブルには機能テストのテスト結果が含まれており、(test_id, request_id)
が主キーです。したがって、test_id
はグループであり、各 test_id
の最後の request_id
を探しています。
Bill のソリューションは私の Dell e4310 で数時間実行されていますが、いつ完了するかわかりません。ただし、カバー インデックスで動作します (したがって、EXPLAIN に示されている
は)。
私も同じ考えに基づいたいくつかの解決策を持っています:
基礎となるインデックスが BTREE インデックスの場合 (通常はこれに当てはまります)、各
(group_id, item_value)
ペアは、各 group_id のペアになります。
インデックスを降順でたどった場合、最後の値は各 group_id
; の最初の値になります。
インデックスでカバーされている値を読み取る場合、値はインデックスの順序で読み取られます。
このソリューションは非常に高速で、1,800 万行のデータに対して約 0.8 秒かかります: リーリー
順序を昇順に変更したい場合は、サブクエリに入れて ID のみを返し、サブクエリとして他の列と結合します。リーリー
私のデータでは、この解決には約 1.2 秒かかります。
解決策 2
これは別の解決策です。私のテーブルでは約 19 秒かかります: リーリー
また、テスト結果を降順で返します。フルインデックススキャンを実行するため速度は遅くなりますが、グループごとに最大 N 行を出力する方法のアイデアが得られます。このクエリの欠点は、その結果をクエリによってキャッシュできないことです。
P粉2677913262023-08-21 09:55:33
MySQL 8.0 は、ほぼすべての一般的な SQL 実装と同様に、ウィンドウ関数をサポートするようになりました。この標準構文を使用すると、グループごとに最大 n 個のクエリを作成できます。 リーリー
MySQL マニュアルでは、この方法とグループ化された最大の行 を見つける他の方法を示しています。
以下は、私が 2009 年にこの質問に対して書いた元の回答です:
リーリー
パフォーマンスに関しては、データの性質によっては、いずれかのソリューションの方が優れている場合があります。したがって、両方のクエリをテストし、データベースのパフォーマンスに基づいてより良い方を選択する必要があります。たとえば、
StackOverflow 8 月のデータ ダンプ のコピーがあります。ベンチマークに使用させていただきます。 Posts テーブルには 1,114,357 行のデータがあります。これは私の Macbook Pro 2.40GHz で
MySQL 5.0.75 を実行しています。
サブクエリで GROUP BY を使用する Eric のテクニックを初めて使用しました:
リーリー
今、LEFT JOINを使用していますMY TECHNIQUEを使用すると、同じクエリ結果が生成されます:
リーリー
EXPLAIN分析の結果、両方のテーブルでインデックスを使用できることがわかりました:
リーリー
Posts テーブルの DDL です:
リーリー
コメント者注: 別のバージョンの MySQL、別のデータセット、または別のテーブル設計を使用して別のベンチマークを実行したい場合は、ご自身で自由に実行してください。上記のテクニックを実証しました。 Stack Overflow の目的は、ソフトウェア開発作業の方法を示すことであり、すべての作業を行うことではありません。