6

インデックスが配置されており、絶対カウント精度が不要であると仮定すると (1 つまたは 2 つずれても問題ありません)、使用しても問題ありません。

オプション A

select count(*) 
  from Table 
 where Property = @Property

オプション B

update PropertyCounters
   SET PropertyCount = PropertyCount + 1  
 where Property = @Property

次に行う:

select PropertyCount 
  from PropertyCounters 
 where Property = @Property

テーブルが数千または数百万のレコードに成長するにつれて、 select count(*) を実行することでどの程度のパフォーマンス低下が合理的に期待できますか?

4

5 に答える 5

5

実際のデータに加えて別のカウント列を保持することは、非正規化です。パフォーマンスのためにそれを行う必要がある理由はいくつかありますが、本当に必要になるまでそこに行くべきではありません。コードがより複雑になり、矛盾が忍び寄る可能性が高くなります。

クエリが本当にただの単純なケースでは、SELECT COUNT(property) FROM table WHERE property=...非正規化する理由はありません。列にインデックスを追加することで、高速化できpropertyます。

于 2010-08-17T01:28:43.397 に答える
3

プラットフォームを指定しませんでしたが、@variables に T-SQL 構文を使用しているため、SQL Server プラットフォーム固有の回答を試してみます。

count(*)、または厳密に言えば はcount_big(*)、インデックス付きビューで使用できる式です。「インデックス付きビューの設計 」を参照してください。

create view vwCounts
with schembinding
as select Property, count_big(*) as Count
from dbo.Table
group by Property;

create unique clustered index cdxCounts on vwCounts(Property);

select Count 
from vwCount with (noexpand)
where Property = @property;

Enterprise Edition では、オプティマイザーは元のクエリにインデックス付きビューを使用します。

select count_big(*)
from Table
where Property = @property;

したがって、最終的にはケーキを手に入れて食べることもできます。プロパティは既に集約されており、エンジンによって無料で維持されています。代償として、更新ではインデックス付きビューを維持する必要があり (ただし、集計カウントは再計算されません)、集計によって競合のホット スポットが作成されます (Table の個別の行のロックは、インデックス付きビューで同じカウント (*) 更新に対して競合します)。 )。

于 2010-08-17T01:42:46.947 に答える
1

絶対的な精度は必要ないと言うなら、オプション B は奇妙なアプローチです。オプション A が重くなりすぎた場合 (インデックスを追加した後でも)、オプション A の出力をメモリまたは別のテーブル (PropertyCounters) にキャッシュし、定期的に更新できます。

于 2010-08-17T02:06:19.573 に答える
0

これは、一般的な SQL 用語で答えられるものではありません。クエリに影響を与えるインデックスなどに関する通常の警告とは別に、プラットフォーム間でかなりの違いがあることでもあります。

これについては、Postgres よりも SQL Server の方が優れたパフォーマンスを発揮することに賭けて、SQL Server ではなく Postgres でより早く後者のアプローチを検討したいと思います。ただし、条件に一致するように設定された部分インデックスを使用すると、Postgres が SQL Server を打ち負かすことに賭けることができます。それは私が少額の賞金を賭けたものであり、実際にそれについて考える必要があるかどうかをテストする.

後者のアプローチを採用する場合は、不正確にならないように、トリガーなどを使用して強制してください。

于 2010-08-17T01:48:00.700 に答える
0

SQL Server では、絶対に正確な数が必要ない場合は、カタログ ビューを調べることもできます。これは、はるかに簡単に実行できます。自分でカウントを維持する必要はありません。また、システムへの負担も大幅に軽減されます。結局のところ、テーブル内のすべての行をカウントする必要がある場合は、何らかの方法でそのテーブルをスキャンする必要があります。それを回避する方法はありません。

この SQL ステートメントを使用すると、データベース内のすべてのテーブルと、SQL Server によって保持されているそれらの行数を取得できます。

SELECT 
    t.NAME AS TableName,
    SUM(p.rows) AS RowCounts
FROM 
    sys.tables t
INNER JOIN      
    sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
WHERE 
    t.NAME NOT LIKE 'dt%' AND
    i.OBJECT_ID > 255 AND   
    i.index_id <= 1
GROUP BY 
    t.NAME, i.object_id, i.index_id, i.name 
ORDER BY 
    OBJECT_NAME(i.object_id) 

通常、これらの数値がどの程度最新のものであるかについてのドキュメントは見つかりませんでしたが、私自身の経験から、それらは通常その場にあります (一括読み込みなどを行っている場合を除きますが、その場合は「常にテーブルをスキャンして正確な数を取得したくない)

于 2010-08-17T05:07:10.457 に答える