SQL 카운트 쿼리 속도를 높일 수있는 것은 무엇입니까?


9

카운트 (집계) SQL 쿼리를 수행 할 때이 3 개의 데이터베이스 시스템에서 실행 시간을 단축 할 수있는 것은 무엇입니까? 나는 많은 것들이 속도를 높일 수 있다고 확신하지만 (하나는 하드웨어), 나는 초보자 DBA 일 뿐이므로 여기에 몇 가지 대답을 얻을 것이라고 확신합니다. 약 1 억 5 천 5 백만 행을 SQL Server 데이터베이스로 마이그레이션했으며이 쿼리는 계속 진행되고 있습니다. 그러나 소스 Netezza 데이터베이스에서는 몇 초가 걸립니다.

예를 들면 다음과 같습니다.

네 테짜 6 :

SELECT COUNT(*) FROM DATABASENAME..MYTABLE

Oracle 11g :

SELECT COUNT(*) FROM MYTABLE

SQL Server 2012 :

SELECT COUNT(*) FROM DATABASENAME.[dbo].[MYTABLE]


1
이 작업을 한 번만 또는 반복해서 수행해야합니까?
Jon Seigel

@JonSeigel 우리는 증분로드를 수행하고 있으며 데이터베이스 시스템 간의 레코드를 매일 비교하여 카운트를 더하고 있습니다. 반복해서.
MacGyver

답변:


10

Netezza는 큰 테이블 스캔에서 탁월하도록 설계된 어플라이언스이므로 해당 시스템에서 빠른 결과를 얻을 수 있습니다.

SQL Server의 경우 sys.dm_db_partition_stats DMV에서 쿼리하여 행 수를 크게 높일 수 있습니다.

SELECT s.name AS [Schema], o.name AS [Table], SUM(p.row_count) AS [RowCount]
FROM sys.dm_db_partition_stats p JOIN sys.objects o
ON p.object_id = o.object_id JOIN sys.schemas s
ON o.schema_id = s.schema_id
WHERE p.index_id < 2
AND o.object_id = object_id('MyTable')
GROUP BY o.name, s.name;

트랜잭션이 많은 환경에서이 DMV는 100 % 정확한 것은 아닙니다. 그러나 귀하의 질문에 따르면, 마이그레이션 후 각 테이블을 확인하기 위해 행 수를 수행하는 것처럼 들리 므로이 쿼리가 효과적입니다.


4
@ 필 왜? 테이블을 반복하고 각 테이블에서 고가의 SELECT COUNT (*)를 수행하면 마지막 테이블에 도달하면 첫 번째 결과가 얼마나 정확합니까?
Aaron Bertrand

1
Phil은 다음과 같이 말했습니다. "100 % 정확한 결과를 제공하지 않는 데이터 사전을 사용하는 것은 좋지 않은 조언입니다. 제 의견으로는 제안을 삭제하거나 삭제하도록 답변을 수정해야합니다. Google은 이러한 답변을 기억하고 맹목적으로 잘라 내기 및 붙여 넣기 ... "면책 조항이 중요하다는 데 동의합니다 (메타 데이터가 합리적인 결과를 반환하지 않는 일부 경우가 있음), 일반적으로 메타 데이터보기를 사용하는 것은 좋지 않은 조언에 동의하지 않습니다.
Aaron Bertrand

5

다음 COUNT_BIG은 인덱싱 된 뷰 내부 를 사용하는 SQL Server 솔루션입니다 . 이렇게하면 큰 테이블 또는 인덱스 스캔의 오버 헤드가없고 후자에 필요한 스토리지가 없어도 트랜잭션에 일관성이있는 수를 얻을 수 있습니다.

CREATE TABLE [dbo].[MyTable](id int);
GO

CREATE VIEW [dbo].[MyTableRowCount]
    WITH SCHEMABINDING
AS

    SELECT
        COUNT_BIG(*) AS TableRowCount
        FROM [dbo].[MyTable];
GO

CREATE UNIQUE CLUSTERED INDEX IX_MyTableRowCount
    ON [dbo].[MyTableRowCount](TableRowCount);
GO

SELECT
    TableRowCount
    FROM [dbo].[MyTableRowCount] WITH(NOEXPAND);

이를 위해서는 단일 초기 스캔이 필요하며 (이를 피할 수는 없음) 증분 테이블 데이터 조작에 약간의 오버 헤드가 추가됩니다. 많은 작은 작업과 달리 많은 데이터로 큰 작업을 수행하는 경우 변경에 대한 오버 헤드는 무시할 만하다고 생각합니다.


@SQLKiwi : 2012 년 이전의 읽기는 어떻게 차단됩니까? SQL Server 버그?
Jon Seigel

@JonSeigel-My $ 0,05 : 오프라인으로 생성 된 일반 테이블의 일반 클러스터형 인덱스가 테이블에 Sch-M 잠금을 적용합니다. 물론 뷰에서는 필요 하지 않지만 이는 인덱스 생성 작업을 변경하여 인덱스 된 뷰에 대한 특별한 경우를 만드는 것을 의미합니다. 이는 SQL2012에서 수행되었습니다. 물론 IMHO.
Fabricio Araujo

3

Oracle에서는 NOT NULL 열의 이진 트리 인덱스를 사용하여 COUNT (*)에 응답 할 수 있습니다. 인덱스는 일반적으로 기본 테이블보다 작기 때문에 대부분의 경우 FULL TABLE SCAN보다 빠릅니다.

그러나 일반 이진 트리 인덱스는 여전히 157 Mrows입니다. 테이블이 동시에 업데이트되지 않으면 (즉, 일괄로드 프로세스 만 해당) 비트 맵 인덱스를 대신 사용할 수 있습니다.

가장 작은 비트 맵 인덱스는 다음과 같습니다.

CREATE BITMAP INDEX ix ON your_table(NULL);

비트 맵 인덱스는 널 항목을 고려합니다. 결과 인덱스는 일반 이진 트리 인덱스 또는 기본 테이블에 비해 작습니다 (백만 행당 20-30 8k 블록).

결과 계획에는 다음 작업이 표시되어야합니다.

----------------------------------------------
| Id  | Operation                     | Name | 
----------------------------------------------
|   0 | SELECT STATEMENT              |      |
|   1 |  SORT AGGREGATE               |      |
|   2 |   BITMAP CONVERSION COUNT     |      |
|   3 |    BITMAP INDEX FAST FULL SCAN| IX   |
----------------------------------------------

테이블이 동시에 업데이트되면 고유 한 값을 가진 비트 맵 인덱스가 경합 지점이되어 사용해서는 안됩니다.


3

Oracle에서 단순 카운트 쿼리는 종종 전체 테이블 대신 인덱스를 스캔하여 실행됩니다. 인덱스는 비트 맵 인덱스이거나 NOT NULL 제약 조건이있는 열에 정의되어야합니다. 전체 테이블 스캔이 필요한보다 복잡한 쿼리의 경우 병렬 쿼리를 사용할 수 있습니다.

병렬 쿼리를 사용하려면 (Enterprise Edition 필요) 최적화 힌트를 사용할 수 있습니다.

select /*+ PARALLEL(mytable, 12) */ count(*) from mytable;

또는 테이블의 모든 쿼리에 대해 병렬 쿼리를 활성화하십시오.

alter table mytable parallel 12;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.