복붙노트

[SQL] 카운트 대 (*) COUNT (1) - SQL 서버

SQL

카운트 대 (*) COUNT (1) - SQL 서버

당신이 사람들의 카운트 사용하는 경우 그냥 궁금 (1) 이상 COUNT (*) 및 성능 또는이 사라 과거의 일에서 이월 된 단지 기존의 습관 경우 눈에 띄는 차이가 있다면?

특정 데이터베이스는 SQL 서버 2005입니다.

해결법

  1. ==============================

    1.다른 점이 없다.

    다른 점이 없다.

    이유:

    "1"은 비 - 널 식 : 그것은 COUNT 같은 그래서 (*). 옵티마이 저는 그것이 무엇인지 그것을 인식 : 사소한.

    동일한는 * (SELECT 존재 또는 1을 선택 (EXISTS ...

    예:

    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 (*)가 ( "125 스칼라 표현"찾기) ANSI-92에서 상세하게 언급

    즉, ANSI 표준은 당신이 무엇을 의미하는지 분명 출혈로 인식합니다. COUNT (1)이 때문에 미신 RDBMS 벤더에 의해 최적화되었다. 그렇지 않으면 그것은 ANSI에 따라 평가 될 것이다

  2. ==============================

    2.SQL Server에서이 문은 같은 계획을 얻을 수 있습니다.

    SQL Server에서이 문은 같은 계획을 얻을 수 있습니다.

    인기 의견과는 달리, 오라클에 그들도 않습니다.

    오라클의 SYS_GUID ()는 매우 계산 집약적 인 기능입니다.

    내 테스트 데이터베이스에서 t_even 1,000,000 행이있는 테이블입니다

    이 쿼리 :

    SELECT  COUNT(SYS_GUID())
    FROM    t_even
    

    기능 요구 사항은 각 SYS_GUID ()을 평가하기 때문에 48초에 대한 실행은, 그것이 NULL이 아니다 확인하기 위해 돌아왔다.

    그러나이 쿼리 :

    SELECT  COUNT(*)
    FROM    (
            SELECT  SYS_GUID()
            FROM    t_even
            )
    

    대한 실행하지만, 2 초, 심지어 doen't 이후 SYS_GUID ()을 평가하려고 (*는 COUNT에 인수 임에도 불구하고 (*))

  3. ==============================

    3.분명히, COUNT (*)와 COUNT (1)은 항상 같은 결과를 반환합니다. 따라서, 하나의 경우 인해 최적화 버그에 효과적으로 것이 다른 것보다 느린했다. 두 형태가 쿼리에서 매우 자주 사용되기 때문에, 그것은 DBMS는 이러한 버그가 수정되지 않은 유지 할 수 있도록하기위한 것은 의미가 없습니다. 따라서 당신은 두 형태의 성능이 (아마) 모든 주요 SQL DBMS에 동일 것을 발견 할 것이다.

    분명히, COUNT (*)와 COUNT (1)은 항상 같은 결과를 반환합니다. 따라서, 하나의 경우 인해 최적화 버그에 효과적으로 것이 다른 것보다 느린했다. 두 형태가 쿼리에서 매우 자주 사용되기 때문에, 그것은 DBMS는 이러한 버그가 수정되지 않은 유지 할 수 있도록하기위한 것은 의미가 없습니다. 따라서 당신은 두 형태의 성능이 (아마) 모든 주요 SQL DBMS에 동일 것을 발견 할 것이다.

  4. ==============================

    4.나는 SQL 서버 팀에서 일을하고 나는 희망 (미안 엔지니어링 팀이 때문에 이전에 수행하지 않은거야, 그래서 내가 이전에 그것을 보지 못했다)이 thread에 몇 점을 명확히 할 수 있습니다.

    나는 SQL 서버 팀에서 일을하고 나는 희망 (미안 엔지니어링 팀이 때문에 이전에 수행하지 않은거야, 그래서 내가 이전에 그것을 보지 못했다)이 thread에 몇 점을 명확히 할 수 있습니다.

    첫째, 테이블 선택 카운트 (*) 대 테이블 선택 카운트 (1) 간의 의미 론적 차이가 없다. 그들은 모든 경우에 동일한 결과를 반환 (그리고 버그가없는 경우입니다). 다른 답변에서 언급 한 바와 같이, 테이블 개수 (열)을 선택하는 것은 의미 상 차이가 항상 수 (*)와 같은 결과를 반환하지 않습니다.

    컴파일 타임 일 및 실행 타임 일 : 둘째, 성능과 관련하여, SQL 서버 (및 SQL 애저)에 문제가 것 두 가지 측면이있다. 컴파일 시간 작업은 현재 구현에서 추가 작업 하찮게 작은 양이다. 때문에, 내부 동작의 일부가 결합 작동 및 최적화 방법 1 열 출력되는 환원 다시 다음의 모든 경우에 열 *의 확장이있다. 나는 그것이 어떤 측정 시험에 표시 것이라고 의심, 그것은 가능성 (예 : 자동 통계, xevent 세션, 쿼리를 저장 오버 헤드, 트리거 등) 내부적으로 발생하는 모든 다른 것들의 소음에서 분실 것이다. 그것은 어쩌면 몇 천 여분의 CPU 명령입니다. 그래서, (1) 컴파일하는 동안 작은 조금 적은 작업 수행 (보통 한 번 일어날과 계획이 여러 후속 실행에 걸쳐 캐시) 계산합니다. 실행 시간의 경우, 가정 계획은 측정 가능한 차이가 없을 것 같습니다. (이전 예제 프로그램 중 하나 개 차이가 - 계획이 동일한 경우 인해 시스템의 다른 요소에 가능성이 높습니다).

    방법에 대한 계획은 잠재적으로 다를 수 있습니다. 이 일이 매우 가능성이 있지만, 현재의 최적화의 구조에 잠재적으로 가능하다. SQL 서버의 최적화는 검색 프로그램 (: 쿼리의 다른 부분에 대한 다양한 대안을 통해 컴퓨터 프로그램 재생 체스 검색을하고 대안을 요하는 적당한 시간에서 가장 저렴한 계획을 찾을 생각)로 작동합니다. 이 검색은 적절한 시간에 쿼리 컴파일 마무리를 유지하기 위해 작동하는 방법에 대한 몇 가지 한계가있다. 가장 사소한 넘어 쿼리를 들어, 검색의 단계가 있습니다 그리고 그들은 최적화 프로그램이 쿼리가 잠재적으로 실행하는 것입니다 생각하는 방법을 비용을 기반으로 쿼리의 트렌치 처리합니다. 이 3 개 주요 검색 단계가 있으며, 각 단계는 이전의 솔루션보다 싼 계획을 찾기 위해 노력하고 공격적인 (비용) 휴리스틱을 실행할 수 있습니다. 궁극적으로, 그것은 지금까지 발견하거나 검색을 계속해야 계획을 반환할지 여부를 결정하려고 각 단계의 끝에 결정 과정이있다. 이 과정은 지금까지 가장 좋은 계획의 예상 비용은 지금까지 발견 대 걸리는 총 시간을 사용합니다. 그래서, CPU를 다른 속도와 다른 시스템에이 (희귀이기는하지만) 때문에 다음 검색 단계로 계속 대 계획을 이전 단계에서 시간 초과에 다른 계획을 얻을 수 있습니다. 이 마지막 단계의 시간 초과 잠재적으로 (하지 대개 문제가 64 비트의 시스템의 모든 메모리를 소비 매우 비싼 쿼리에 메모리 부족에 관한 몇 가지 유사한 시나리오는하지만 그것은 더 큰 문제였다 32 비트 서버 다시). 다른 계획을 얻을 경우 궁극적으로, 실행시 성능은 다를 것이다. 나는 그것이 원격 가능성이 컴파일 시간의 차이가 이제까지 일어나는 이러한 조건으로 이어질 것이라고 생각하지 않습니다.

    인터넷-NET : 두 당신은 어떤 실제적인 형태로이 문제의 없음으로 원하는 중하시기 바랍니다 사용. (훨씬 더 큰 요인 정직하게이 주제를 넘어 SQL의 성능에 영향을 미치는, 즉, 지금까지있다).

    이게 도움이 되길 바란다. 나는 그것의 적절한는 여기에 게시하는 경우 (여전히 내가 생각에서 내가 작은 로열티를 얻을로) 최적화 작동하지만 나도 몰라 방법에 대한 책 장을 기록했다. 당신이 원하는 경우에 당신이 좀 더 자세히 검색의 다른 주요 단계를 볼 수 있도록 그래서, 대신 게시물의 난 최적화가 높은 수준에서 작동 방법에 대한 영국의 SQLBits에서 준 이야기에 대한 링크를 게시 할거야 그것에 대해 배울 수 있습니다. 여기에 동영상 링크는 다음과 같습니다 https://sqlbits.com/Sessions/Event6/inside_the_sql_server_query_optimizer

  5. ==============================

    5.는 SQL-92 표준에서, COUNT (*)는 특히 "테이블 식의 카디널리티"(등 기본 테이블`VIEW 파생 테이블 CTE를 될 수 있음)을 의미한다.

    는 SQL-92 표준에서, COUNT (*)는 특히 "테이블 식의 카디널리티"(등 기본 테이블`VIEW 파생 테이블 CTE를 될 수 있음)을 의미한다.

    나는 아이디어가 COUNT (*)이었다 구문 분석 용이 같아요. 파서 다른식이 필요 사용하여 그것이 어떤 열을 참조하지 않도록 내지 ((COUNT를 'A')는 어디 A A 열에 다른 결과를 얻을 수있는 곳) 리터럴 및 COUNT (a).

    같은 맥락에서, (*) COUNT 쉽게 SQL 표준, 하나 개 이상의 공급 업체의 SQL을 제공하는 작업에 유용한 기술을 잘 알고 코더 인간에 의해 포착 될 수있다.

    또한, MyPersistedTable FROM 특별한 경우 SELECT COUNT (*)에 기재 한 사고는 DBMS 테이블의 카디널리티 보류 통계에 가능성이있다.

    COUNT (1) 및 COUNT (*)이 의미 론적으로 동일하기 때문에, 따라서, I는 COUNT (*)를 사용한다.

  6. ==============================

    6.COUNT (*) 및 COUNT (1)의 결과와 성능의 경우와 동일하다.

    COUNT (*) 및 COUNT (1)의 결과와 성능의 경우와 동일하다.

  7. ==============================

    7.나는 옵티마이 이상한 가장자리의 경우 외부는 아무런 실질적 차이가 없다 보장하기 위해 기대.

    나는 옵티마이 이상한 가장자리의 경우 외부는 아무런 실질적 차이가 없다 보장하기 위해 기대.

    아무와 마찬가지로 말할 수있는 유일한 방법은 특정 케이스를 측정하는 것입니다.

    난 항상 COUNT (*)를 사용했습니다 말했다.

  8. ==============================

    8.이 질문은 또 다시 오면, 여기에 또 하나의 대답이다. 여기 "가장 좋은 방법"에 대해 궁금 초보자를위한 뭔가를 추가 할 수 있도록 노력하겠습니다.

    이 질문은 또 다시 오면, 여기에 또 하나의 대답이다. 여기 "가장 좋은 방법"에 대해 궁금 초보자를위한 뭔가를 추가 할 수 있도록 노력하겠습니다.

    쉬운 일이 뭔가 카운트 기록 FROM SELECT COUNT (*).

    뭔가 FROM SELECT COUNT (1) 1 레코드 당과 본질적으로 기록을 기대하고있다 null이 아닌 1 초는, 단지 더 복잡한 계산보다는 검색합니다.

    데이 말을 : 좋은 DBMS 두 번째 문이 첫 번째 문 그에 맞게 재 interprete 같은 카운트됩니다뿐만되지 불필요한 작업을 수행하는 것을 알 수 있습니다. 그래서 일반적으로 두 문은 같은 실행 계획 결과와 동일한 시간이 소요됩니다.

    그러나 가독성의 관점에서 첫 번째 문을 사용해야합니다. 당신은 기록을 셀 수 있기 (위해) 때문에, 기록하지 표현식을 계산합니다. 당신이 뭔가의 null 이외의 발행 수를 계산하려는 경우에만 사용 COUNT (표현식).

  9. ==============================

    9.나는 8 기가 바이트 RAM Hyper-V를 상자에 SQL 서버 2012 빠른 테스트를 실행. 당신은 자신에 대한 결과를 볼 수 있습니다. 이러한 테스트를 실행하는 동안 나는 SQL Server 관리 Studio에서 떨어져 다른 윈도우 응용 프로그램을 실행하지 않았다.

    나는 8 기가 바이트 RAM Hyper-V를 상자에 SQL 서버 2012 빠른 테스트를 실행. 당신은 자신에 대한 결과를 볼 수 있습니다. 이러한 테스트를 실행하는 동안 나는 SQL Server 관리 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
    

    직원 테이블의 레코드의 총 수 : 178,090,131 (~ 178,000,000 행)

    첫 번째 쿼리 :

    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.
    

    두 번째 쿼리 :

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

    두 번째 쿼리의 결과 :

     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 (70,182 = 70,265)의 차이가 나타날 수 있습니다. 내가 몇 실행을하고 약간의 평균을 할 경우이 차이는 더 정확하게 될 것이다, 그래서 또한 나는, 단일 실행했다. 이러한 큰 차이는 100 밀리 초 미만오고있다 데이터 세트에 대한 경우, 우리는 쉽게 두 쿼리는 SQL 서버 엔진에 의해 전시 된 모든 성능 차이가없는 것으로 결론을 내릴 수있다.

    참고 : RAM 히트는 모두 타점을 100 % 사용에 닫습니다. 나는 모두 실행을 시작하기 전에 SQL Server 서비스를 다시 시작됩니다.

  10. ==============================

    10.

    SET STATISTICS TIME ON
    
    select count(1) from MyTable (nolock) -- table containing 1 million records. 
    
    select count(*) from MyTable (nolock) -- table containing 1 million records. 
    

    나는 서버 부하의 변화에 ​​따라 캐시 때마다 청소 시간이 수백 .. 결과는 때때로 한 쳤 다양하지만, 거의 항상 COUNT (*) 높은 CPU 시간을 가지고있다.

  11. ==============================

    11.오라클에 COUNT (1) 그것에 대해 증거와 COUNT (*) 단지의 별칭이라고 보여주는 기사가있다.

    오라클에 COUNT (1) 그것에 대해 증거와 COUNT (*) 단지의 별칭이라고 보여주는 기사가있다.

    나는 일부를 인용합니다 :

    ALTER SESSION 권한을 가진 사용자로, 당신은 같은 추적 최적화를 가능하게하는 tracefile_identifier을 넣고 (1) 선택 COUNT를 실행할 수 있습니다 직원 FROM SELECT / * 테스트 1 * / COUNT (1);

    그 후, 당신은 WHERE NAME = '의 하단부 추적'V $ DIAG_INFO에서 선택 VALUE와 함께 할 수있는 추적 파일을 지역화 할 필요가 ;. 나중에 파일에, 당신은 발견 할 것이다 :

    SELECT COUNT(*) “COUNT(1)” FROM “COURSE”.”EMPLOYEES” “EMPLOYEES”
    

    당신이 볼 수 있듯이, 그것은 단지 COUNT (*)의 별칭이다.

    또 다른 중요한 코멘트 : 오라클 7.3 전에, 오라클에 20 년전 정말 빨랐다 (*)를 COUNT :

    는 SQL Server와 같은 다른 데이터베이스의 경우, 그것은 각각에 대해 개별적으로 연구해야한다.

    나는이 대답에서 중복으로이 문제는 SQL Server의 경우 특정 있지만, 같은 주제에 대한 SO의 다른 질문에 대한 언급없이, 폐쇄 및 표시되었다 데이터베이스는 것을 알고있다.

  12. ==============================

    12.모든 RDBMS에서 계산의 두 가지 방법은 그들이 생산 결과 어떤면에서 동일합니다. 성능에 관해서는, 나는 SQL 서버에서 어떤 성능 차이를 관찰하지 않은,하지만 그것은 가치가 지적하는 일부 RDBMS, 예를 들어있을 수 있습니다 이 게시물에서 볼 수있는 것처럼 그들이 인수 식의 Null 허용 여부를 확인으로 PostgreSQL을 (11), COUNT (1) 적은 최적의 구현을 가지고있다.

    모든 RDBMS에서 계산의 두 가지 방법은 그들이 생산 결과 어떤면에서 동일합니다. 성능에 관해서는, 나는 SQL 서버에서 어떤 성능 차이를 관찰하지 않은,하지만 그것은 가치가 지적하는 일부 RDBMS, 예를 들어있을 수 있습니다 이 게시물에서 볼 수있는 것처럼 그들이 인수 식의 Null 허용 여부를 확인으로 PostgreSQL을 (11), COUNT (1) 적은 최적의 구현을 가지고있다.

    나는 1M 행을 실행하기위한 10 %의 성능 차이를 발견했습니다 :

    -- Faster
    SELECT COUNT(*) FROM t;
    
    -- 10% slower
    SELECT COUNT(1) FROM t;
    
  13. ==============================

    13.모든 경우에서 COUNT (1), COUNT (*)과 실질적으로 다르지 않다. 별도의 조회 계산의 문제에 관해서는,이 COUNT (*)와 COUNT의 차이점을 데모하는 간단 할 수있다 (<일부 COL>) -

    모든 경우에서 COUNT (1), COUNT (*)과 실질적으로 다르지 않다. 별도의 조회 계산의 문제에 관해서는,이 COUNT (*)와 COUNT의 차이점을 데모하는 간단 할 수있다 (<일부 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
    
  14. from https://stackoverflow.com/questions/1221559/count-vs-count1-sql-server by cc-by-sa and MIT license