사람들 중 일부를 Count(1)
과도하게 사용 하고 Count(*)
성능에 눈에 띄는 차이가 있는지 또는 과거의 일에서 제기 된 레거시 습관인지 궁금하십니까?
특정 데이터베이스는 SQL Server 2005
입니다.
답변
다른 점이 없다.
이유:
온라인 서적에 ”
COUNT ( { [ [ ALL | DISTINCT ] expression ] | * } )
“
“1”은 널이 아닌 표현식입니다. 따라서와 동일합니다 COUNT(*)
. 옵티마이 저는이를 사소한 것으로 인식합니다.
와 동일 EXISTS (SELECT * ...
또는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 월 편집
2011 년 12 월 수정
COUNT(*)
ANSI-92에 구체적으로 언급되어 있습니다 ( ” Scalar expressions 125
“)
케이스:
a) COUNT (*)가 지정되면 결과는 T의 카디널리티입니다.
즉, ANSI 표준은이를 의미하는 출혈로 인식합니다. 이 미신 때문에COUNT(1)
RDBMS 공급 업체가 최적화했습니다 . 그렇지 않으면 ANSI에 따라 평가됩니다
b) 그렇지 않으면 TX가 <value expression>을 T의 각 행에 적용하고 널값을 제거한 결과 인 단일 열 테이블이되게하십시오. 하나 이상의 널값이 제거되면 완료 조건이 발생합니다. warning-
답변
SQL Server에서 이러한 명령문은 동일한 계획을 산출합니다.
대중의 의견과는 달리, 오라클에서도 마찬가지입니다.
SYS_GUID()
오라클에서는 계산 집약적 인 기능입니다.
내 테스트 데이터베이스에서 행 t_even
이있는 테이블입니다.1,000,000
이 쿼리 :
SELECT COUNT(SYS_GUID())
FROM t_even
48
함수가 SYS_GUID()
반환 된 각 값을 평가하여이 값 이 아닌지 확인 해야하기 때문에 몇 초 동안 실행됩니다 NULL
.
그러나이 쿼리는 다음과 같습니다.
SELECT COUNT(*)
FROM (
SELECT SYS_GUID()
FROM t_even
)
2
평가조차하지 않기 때문에 몇 초 동안 실행됩니다 (에 대한 논쟁 SYS_GUID()
에도 불구하고 )*
COUNT(*)
답변
분명히, COUNT(*)
그리고 COUNT(1)
것입니다 항상 같은 결과를 반환합니다. 따라서 하나가 다른 것보다 느리면 효과적으로 최적화 버그로 인한 것입니다. 두 형식 모두 쿼리에서 매우 자주 사용되므로 DBMS가 이러한 버그를 수정하지 않은 상태로 유지하는 것은 의미가 없습니다. 따라서 모든 주요 SQL DBMS에서 두 양식의 성능이 동일 할 것입니다.
답변
SQL Server 팀에서 일하고 있으며이 스레드에서 몇 가지 요점을 명확하게 설명 할 수 있습니다 (이전에 본 적이 없으므로 엔지니어링 팀이 이전에 수행하지 않은 것이 유감입니다).
첫째, 사이에 의미 차이가없는 select count(1) from table
비교는 select count(*) from table
. 그들은 모든 경우에 동일한 결과를 반환합니다 (그렇지 않으면 버그입니다). 다른 답변에서 언급했듯이 select count(column) from table
의미 적으로 다르며 항상 같은 결과를 반환하지는 않습니다 count(*)
.
둘째, 성능과 관련하여 SQL Server (및 SQL Azure)에서 중요한 두 가지 측면, 즉 컴파일 타임 작업과 실행 타임 작업이 있습니다. 컴파일 시간 작업은 현재 구현에서 사소한 추가 작업입니다. 일부 경우에 *를 모든 열로 확장 한 후 일부 내부 조작이 바인딩 및 최적화에서 작동하는 방식으로 인해 출력이 1 열로 다시 축소됩니다. 나는 그것이 측정 가능한 테스트에 나타날 것이라고 의심하고, 커버 아래에서 발생하는 다른 모든 것들 (예 : 자동 통계, xevent 세션, 쿼리 저장소 오버 헤드, 트리거 등)에서 잡음이 손실 될 수 있습니다. 수천 개의 추가 CPU 명령어 일 수 있습니다. 그래서, count (1)은 컴파일하는 동안 약간의 작업을 덜 수행합니다 (일반적으로 한 번 발생하며 계획은 여러 후속 실행에서 캐시 됨). 실행 시간 동안 계획이 동일하다고 가정하면 측정 가능한 차이가 없어야합니다. (이전 예제 중 하나는 차이점을 보여줍니다. 계획이 동일한 경우 시스템의 다른 요인으로 인한 것일 수 있습니다).
계획이 어떻게 다를 수 있는지에 대해. 이러한 상황은 거의 발생하지 않지만 현재 옵티마이 저의 아키텍처에서 가능할 수 있습니다. SQL Server의 옵티마이 저는 검색 프로그램으로 작동합니다 (컴퓨터 프로그램은 쿼리의 다른 부분에 대한 다양한 대안을 통해 체스 검색을 수행하고 합리적인 시간에 가장 저렴한 계획을 찾기 위해 대안을 계산합니다). 이 검색에는 쿼리 컴파일을 적절한 시간 내에 완료하기 위해 작동하는 방식에 몇 가지 제한이 있습니다. 가장 사소한 쿼리 이외의 쿼리에는 검색 단계가 있으며 쿼리가 잠재적으로 쿼리를 실행하는 데 비용이 얼마나 많이 드는지에 따라 쿼리 트랜치를 처리합니다. 3 가지 주요 검색 단계가 있으며 각 단계는 이전 솔루션보다 저렴한 요금제를 찾으려고보다 공격적인 (비싼) 휴리스틱을 실행할 수 있습니다. 궁극적으로 각 단계의 끝에는 지금까지 찾은 계획을 반환해야하는지 또는 계속 검색해야하는지 결정하는 결정 프로세스가 있습니다. 이 프로세스는 지금까지 걸린 총 계획 시간과 지금까지 찾은 최상의 계획의 예상 비용을 사용합니다. 따라서 CPU 속도가 다른 여러 시스템에서 계획이있는 이전 단계에서 다음 검색 단계로 진행하여 이전 단계에서 시간이 초과되어 다른 계획을 얻을 수 있습니다 (드물지만). 마지막 단계의 시간 초과 및 시스템의 모든 메모리를 소비하는 매우 고가의 쿼리에서 잠재적으로 메모리 부족과 관련된 몇 가지 유사한 시나리오도 있습니다 (일반적으로 64 비트의 문제는 아니지만 더 큰 관심 사임) 32 비트 서버로 돌아 가기). 궁극적으로 다른 계획을 세우면 런타임시 성능이 달라집니다. 나는
인터넷 :이 두 가지 중 어느 것도 원하는 형태로 사용하지 마십시오. (이 주제 이상으로 SQL 성능에 영향을 미치는 훨씬 더 큰 요소가 솔직히 있습니다).
이게 도움이 되길 바란다. 옵티마이 저의 작동 방식에 대한 책 장을 작성했지만 여기에 게시하는 것이 적절한 지 모르겠습니다. 따라서 영국의 SQLBits에서 최적화 프로그램이 높은 수준으로 작동하는 방식에 대해 이야기 한 링크에 게시한다고 게시하면 원하는 경우 검색의 다른 주요 단계를 좀 더 자세히 볼 수 있습니다 그것에 대해 배울 수 있습니다. 비디오 링크는 다음과 같습니다. https://sqlbits.com/Sessions/Event6/inside_the_sql_server_query_optimizer
답변
SQL-92 Standard에서 COUNT(*)
구체적으로 “테이블 표현식의 카디널리티”(기본 테이블,`VIEW, 파생 테이블, CTE 등일 수 있음)를 의미합니다.
아이디어가 COUNT(*)
파싱하기 쉽다 는 생각이 들었습니다. 다른 표현을 사용하는 것은 임의의 열을 참조하지 않도록 할 필요 파서 ( COUNT('a')
여기서 a
리터럴 및 COUNT(a)
곳 a
이다 열 다른 결과를 얻을 수있다).
같은 맥락에서, COUNT(*)
하나 이상의 벤더의 SQL 오퍼링을 작업 할 때 유용한 기술인 SQL 표준에 익숙한 인간 코더가 쉽게 선택할 수 있습니다.
또한 특별한 경우 SELECT COUNT(*) FROM MyPersistedTable;
DBMS가 테이블의 카디널리티에 대한 통계를 보유 할 가능성이 있다고 생각합니다.
때문에 따라서, COUNT(1)
그리고 COUNT(*)
의미 동일, 내가 사용 COUNT(*)
.
답변
COUNT(*)
그리고 COUNT(1)
그 결과 성능의 경우와 동일하다.
답변
옵티마이 저가 이상한 경우를 제외하고는 실질적인 차이가 없는지 확인해야합니다.
다른 것과 마찬가지로, 실제로 말할 수있는 유일한 방법은 특정 사례를 측정하는 것입니다.
즉, 나는 항상 사용했습니다 COUNT(*)
.