純粋なSQL
2008年以降、状況が変わりました。ウィンドウ関数を使用して、フルカウントを取得できますおよび 1つのクエリで限られた結果。 2009年にPostgreSQL8.4で導入されました。
SELECT foo
, count(*) OVER() AS full_count
FROM bar
WHERE <some condition>
ORDER BY <some col>
LIMIT <pagesize>
OFFSET <offset>;
これは合計数がない場合よりもかなり高くなる可能性があることに注意してください 。すべての行をカウントする必要があり、一致するインデックスから一番上の行だけを取得する可能性のあるショートカットは、もはや役に立たない場合があります。
小さなテーブルや full_count
ではそれほど重要ではありません。 <=オフセットコード> +
LIMIT
。大幅に大きいfull_count
の問題 。
コーナーケース : OFFSET
の場合 少なくとも基本クエリの行数と同じです。行なし が返されます。したがって、 full_count
も取得されません 。考えられる代替案:
- LIMIT / OFFSETを使用してクエリを実行し、行の総数も取得します
SELECT
のイベントのシーケンス クエリ
(0. CTEは個別に評価され、具体化されます。Postgres12以降では、プランナーは作業に行く前にサブクエリなどをインライン化する場合があります。)ここではありません。
場所
句(およびJOIN
条件(ただし、この例ではありません)は、ベーステーブルから修飾行をフィルタリングします。 残りはフィルタリングされたサブセットに基づいています。
(2. GROUP BY
集計関数はここにあります。)ここではありません。
(3.その他の SELECT
リスト式は、グループ化/集約された列に基づいて評価されます。)ここではありません。
-
OVER
に応じてウィンドウ関数が適用されます 節と関数のフレーム仕様。単純なcount(*)OVER()
対象となるすべての行に基づいています。 -
ORDER BY
(6. DISTINCT
またはDISTINCTON
ここに行きます。)ここではありません。
-
LIMIT
/オフセットコード> 確立された順序に基づいて適用され、返される行が選択されます。
LIMIT
/オフセットコード> テーブル内の行数が増えると、非効率になります。より良いパフォーマンスが必要な場合は、別のアプローチを検討してください。
- 大きなテーブルでOFFSETを使用してクエリを最適化する
最終カウントを取得するための代替案
影響を受ける行の数を取得するには、まったく異なるアプローチがあります(ない OFFSET
の前のフルカウント & LIMIT
適用されました)。 Postgresには、最後のSQLコマンドの影響を受ける行数を内部で記録しています。一部のクライアントは、その情報にアクセスしたり、行自体をカウントしたりできます(psqlなど)。
たとえば、影響を受ける行の数を plpgsqlで取得できます。 次のコマンドを使用してSQLコマンドを実行した直後:
GET DIAGNOSTICS integer_var = ROW_COUNT;
マニュアルの詳細。
または、 pg_num_rows
を使用できます PHP 。または他のクライアントの同様の機能。
関連:
- PostgreSQLでバッチクエリの影響を受ける行数を計算する