Eclipselink、Spring Data、Postgresqlを使用しています。私のプロジェクトでは、SpringDataリポジトリによって提供されるページ結果を使用すると、次のようなクエリがあることに気付きました。
SELECT COUNT(id)
FROM table
WHERE [part generated according to specification]
ここで、「id」は「table」の主キーです。Explainを掘り下げると、非常に大きなテーブルの場合、COUNT(id)はCOUNT()よりも約10倍遅いことに気付きました(count(id)は「id」列でnull以外の値を探しますが、count()は単に一致する行数を返します基準)、count(*)もインデックスを利用できますが、count(id)は利用できません。
SpringDataの基本リポジトリクラスをトレースしましたが、このクエリの生成はJPA実装のみが担当しているようです。
助けていただければ幸いです
-[編集]-
机がある:
\d ord_order
Table "public.ord_order"
Column | Type | Modificators
-------------------------+--------------------------+----------------------------------------------------------
id | integer | NOT NULL DEFAULT nextval('ord_order_id_seq'::regclass)
test_order | boolean | DEFAULT false
...
Indexes:
"pk_order" PRIMARY KEY, btree (id)
"idx_test_order" btree (test_order)
# explain SELECT COUNT(*) FROM ord_order WHERE (test_order = false);
QUERY PLAN
--------------------------------------------------------------------------
Aggregate (cost=89898.79..89898.80 rows=1 width=0)
-> Index Only Scan using idx_test_order on ord_order (cost=0.43..85375.37 rows=1809366 width=0)
Index Cond: (test_order = false)
Filter: (NOT test_order)
(4 wiersze)
# explain SELECT COUNT(id) FROM ord_order WHERE (test_order = false);
QUERY PLAN
--------------------------------------------------------------------------
Aggregate (cost=712924.52..712924.53 rows=1 width=4)
-> Seq Scan on ord_order (cost=0.00..708401.10 rows=1809366 width=4)
Filter: (NOT test_order)
(3 wiersze)
現在、違いは〜90k対〜713kであり、インデックススキャンとフルスキャンの違いです。
私は、カスタムのSpring DataRepository基本クラスの実装とその実装を使用したファクトリを提供することができました。結果として、生成されたカウントクエリは次の形式になります。
SELECT COUNT(1) FROM table
COUNT(*)と同じプランです。これは優れたソリューションのようであり、アプリケーションで定義されているすべてのリポジトリに対してグローバルに機能します。
COUNT(*)を生成する方法がわかりませんでした。COUNT関数はパラメーターとしていくつかの式を予期し、静的な値を指定できるため、COUNT(1)ははるかに簡単でした-1
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加