違い - sql count(1) 意味




カウント(*)とカウント(1)-SQL Server (8)

Count(*)を使ってCount(1)を使用しているのか、パフォーマンスに顕著な差があるのか​​、これが過去の日々からもたらされた伝統的な習慣であるのか疑問に思うだけです。

(特定のデータベースはSQL Server 2005です。)


COUNT(*)対COUNT(<some col>)のデモを簡単に -

USE tempdb;
GO

IF OBJECT_ID( N'dbo.Blitzen', N'U') IS NOT NULL DROP TABLE dbo.Blitzen;
GO

CREATE TABLE dbo.Blitzen (ID INT NULL, Somelala CHAR(1) NULL);

INSERT dbo.Blitzen SELECT 1, 'A';
INSERT dbo.Blitzen SELECT NULL, NULL;
INSERT dbo.Blitzen SELECT NULL, 'A';
INSERT dbo.Blitzen SELECT 1, NULL;

SELECT COUNT(*), COUNT(1), COUNT(ID), COUNT(Somelala) FROM dbo.Blitzen;
GO

DROP TABLE dbo.Blitzen;
GO

SQL Server 2012の8 GB RAMハイパーVボックスでのクイックテストを実行しました。 あなたは自分のために結果を見ることができます。 これらのテストを実行している間は、SQL Server Management Studio以外のウィンドウアプリケーションは実行していませんでした。

私のテーブルのスキーマ:

CREATE TABLE [dbo].[employee](
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_employee] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

Employeeテーブルのレコードの総数:178090131(〜178 million rows)

最初のクエリ:

Set Statistics Time On
Go    
Select Count(*) From Employee
Go    
Set Statistics Time Off
Go

最初のクエリの結果:

 SQL Server parse and compile time: 
 CPU time = 0 ms, elapsed time = 35 ms.

 (1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 10766 ms,  elapsed time = 70265 ms.
 SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

2番目のクエリ:

    Set Statistics Time On
    Go    
    Select Count(1) From Employee
    Go    
    Set Statistics Time Off
    Go

2番目のクエリの結果:

 SQL Server parse and compile time: 
   CPU time = 14 ms, elapsed time = 14 ms.

(1 row(s) affected)

 SQL Server Execution Times:
   CPU time = 11031 ms,  elapsed time = 70182 ms.
 SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

クエリが実行されたときの正確なシステム状態に起因すると思われる83(= 70265-70182)ミリ秒の違いがあることがわかります。 また、私は1回実行したので、いくつかの実行を行い、いくつかの平均化を行うと、この差はより正確になります。 このような巨大なデータセットの差が100ミリ秒未満になると、2つのクエリでSQL Server Engineが示すパフォーマンスの差異がないと簡単に判断できます。

:両方の実行でRAMが100%近く使用されます。 両方の実行を開始する前に、SQL Serverサービスを再起動しました。


SQL-92標準では、 COUNT(*)具体的には「テーブル式のカーディナリティ」を意味します(ベーステーブル、VIEW、派生テーブル、CTEなど)。

私は、 COUNT(*)を解析するのは簡単だと思った。 他の式を使用する場合、パーサーは、aがリテラルでa COUNT('a')aが列でa COUNT(a)が異なる結果をもたらす可能性のある列を参照しないようにパーサーに要求します。

同様に、 COUNT(*)は、複数のベンダーのSQL製品を扱う際に役立つ、SQL標準に精通した人間のコーダーが簡単に選ぶことができます。

また、特別なケースでは、 SELECT COUNT(*) FROM MyPersistedTable; DBMSはテーブルのカーディナリティに関する統計を保持する可能性が高いと考えています。

したがって、 COUNT(1)COUNT(*)は意味的に同等であるため、 COUNT(*)を使用します。


COUNT(*)COUNT(1)は、結果とパフォーマンスの場合は同じです。


この質問が何度も繰り返されるにつれて、もう一つの答えがあります。 私はここで "ベストプラクティス"について不思議な初心者のために何かを追加したいと思っています。

SELECT COUNT(*) FROM something 、簡単な作業であるレコードを数えます。

SELECT COUNT(1) FROM something 、1レコードにつき1を検索し、nullではない1を数えます。

良いdbmsは、2番目のステートメントが最初のステートメントと同じカウントになることに気づき、不必要な作業をしないようにそれに応じて再補間します。 したがって、通常は両方のステートメントが同じ実行計画になり、同じ時間がかかります。

しかし、読みやすさの点から、最初のステートメントを使用するべきです。 レコードを数えたいので、式ではなくレコードを数えます。 COUNT(式)は、何かのnull以外の発生をカウントする場合にのみ使用します。


明らかに、COUNT(*)とCOUNT(1)は常に同じ結果を返します。 したがって、一方が他方よりも遅い場合は、オプティマイザのバグが原因です。 どちらの形式もクエリで頻繁に使用されるため、DBMSがこのようなバグを修正しないままにすることはできません。 したがって、両方のフォームのパフォーマンスは、すべての主要なSQL DBMSで(おそらく)同じであることがわかります。


違いはありません。

理由:

オンラインの書籍には「 COUNT ( { [ [ ALL | DISTINCT ] expression ] | * } ) 」と表示されます。

"1"はnull以外の式なので、 COUNT(*)と同じです。 オプティマイザはそれを認識します。

EXISTS (SELECT * ...またはEXISTS (SELECT 1 ...と同じEXISTS (SELECT 1 ...

例:

SELECT COUNT(1) FROM dbo.tab800krows
SELECT COUNT(1),FKID FROM dbo.tab800krows GROUP BY FKID

SELECT COUNT(*) FROM dbo.tab800krows
SELECT COUNT(*),FKID FROM dbo.tab800krows GROUP BY FKID

同じIO、同じ計画、作品

編集、2011年8月

DBA.SEに関する同様の質問

編集、2011年12月

COUNT(*)は特にANSI-92に Scalar expressions 125ます(「 Scalar expressions 125 」を参照)

場合:

a)COUNT(*)が指定されている場合、結果はTの基数になります。

つまり、ANSI標準では、それが明らかに出血していると認識しています。 COUNT(1)はこの迷信のためにRDBMSベンダーによって最適化されています。 それ以外の場合は、ANSI

b)そうでなければ、TXをTの各行に<値式>を適用してヌル値を取り除いた結果の単一列の表とします。 1つ以上のヌル値が除去されると、完了条件が発生します:warning-


SET STATISTICS TIME ON

select count(1) from MyTable (nolock) -- table containing 1 million records. 

SQL Serverの実行時間:
CPU時間= 31ms、経過時間= 36ms。

select count(*) from MyTable (nolock) -- table containing 1 million records. 

SQL Serverの実行時間:
CPU時間= 46ms、経過時間= 37ms。

私はこれを数百回実行し、毎回キャッシュをクリアしました。サーバの負荷が変化するにつれて結果は時々刻々と変化しますが、ほとんどの場合(*)はCPU時間が長くなります。





performance