[sql] 매우 큰 테이블에서 정확한 수의 행을 계산하는 가장 빠른 방법은 무엇입니까?

나는 다음과 같은 내용의 기사를 보았습니다. SELECT COUNT(*) FROM TABLE_NAME테이블에 많은 행과 많은 열이있을 때 속도가 느린 보았습니다.

수십억 개의 행 (약 15 개의 열이 있음)을 포함 할 수있는 테이블이 있습니다. 정확한 정보 를 얻는 더 좋은 방법이 있습니까테이블의 행 수에 대한 개수 있습니까?

답변하기 전에 다음 사항을 고려하십시오.

  • 데이터베이스 공급 업체 독립 솔루션을 찾고 있습니다. 그것이 MySQL , Oracle , MS SQL Server를 포함한다면 괜찮습니다 . 그러나 실제로 데이터베이스 벤더 독립 솔루션이 없다면 다른 데이터베이스 벤더에 대해 다른 솔루션을 결정합니다.

  • 다른 외부 도구를 사용하여이 작업을 수행 할 수 없습니다. 주로 SQL 기반 솔루션을 찾고 있습니다.

  • 더 이상 데이터베이스 디자인을 정규화 할 수 없습니다. 이미 3NF에 있으며 많은 코드가 이미 작성되었습니다.



답변

간단한 답변 :

  • 데이터베이스 벤더 독립 솔루션 = 표준 사용 = COUNT(*)
  • 있다 대략 SQL 서버 솔루션은 그러나 범위를 벗어난 = COUNT (*)를 사용하지 않는

노트:

COUNT (1) = COUNT (*) = COUNT (PrimaryKey) 경우에 대비하여

편집하다:

SQL Server 예 (14 억 행, 12 열)

SELECT COUNT(*) FROM MyBigtable WITH (NOLOCK)
-- NOLOCK here is for me only to let me test for this answer: no more, no less

1 회, 5:46 분, 카운트 = 1,401,659,700

--Note, sp_spaceused uses this DMV
SELECT
   Total_Rows= SUM(st.row_count)
FROM
   sys.dm_db_partition_stats st
WHERE
    object_name(object_id) = 'MyBigtable' AND (index_id < 2)

2 초, 1 초 미만, 카운트 = 1,401,659,670

두 번째 행은 행 수가 적습니다. 쓰기에 따라 동일하거나 더 많을 수 있습니다 (삭제는 몇 시간이 지나면 완료 됨)


답변

MySQL에서 가장 빠른 방법은 다음과 같습니다.

SHOW TABLE STATUS;

원하는 경우 많은 수의 추가 정보와 함께 행 수 (전체)와 함께 모든 테이블을 즉시 가져올 수 있습니다.


답변

테이블에 행과 열이 많을 때 SELECT COUNT (*) FROM TABLE_NAME이 느리다는 기사가 나왔습니다.

데이터베이스에 따라 다릅니다. 예를 들어 인덱스에서 행의 존재 여부를 추적하여 인덱스 만 스캔하면 행 수를 추출 할 수 있습니다. 다른 사람들은 전체 테이블을 방문하지 않고 라이브 행을 하나씩 계산해야합니다. 거대한 테이블의 경우 속도가 느려집니다.

일반적으로 쿼리 최적화 도구, 테이블 통계 등을 사용하여 적절한 추정치를 추출 할 수 있습니다. 예를 들어 PostgreSQL의 경우 출력을 구문 분석하고 explain count(*) from yourtable행 수를 합리적으로 추정 할 수 있습니다. 두 번째 질문으로 연결됩니다.

수십억 개의 행을 포함 할 수있는 테이블이 있습니다 (약 15 개의 열이 있음). 테이블의 행 수에 대한 정확한 개수를 얻는 더 좋은 방법이 있습니까?

진심이야? 🙂 당신은 정말 정확한 의미 수십억 개의 행이있는 테이블에서 수를 합니까? 정말로 확신합니까? 🙂

실제로 할 경우 트리거를 사용하여 총계를 추적 할 수는 있지만 동시성 및 교착 상태를 염두에 두십시오.


답변

테이블의 행 수에 대한 정확한 개수를 얻는 더 좋은 방법이 있습니까?

귀하의 질문에 간단히 대답하려면 아니오 .

이 작업을 수행하는 DBMS 독립적 방법이 필요한 경우 가장 빠른 방법은 항상 다음과 같습니다.

SELECT COUNT(*) FROM TableName

일부 DBMS 공급 업체는 시스템에서만 작동하는 더 빠른 방법이있을 수 있습니다. 이러한 옵션 중 일부는 이미 다른 답변에 게시되어 있습니다.

COUNT(*) 어쨌든 DBMS (적어도 PROD 가치있는 DB)에 의해 최적화되어야하므로 최적화를 우회하지 마십시오.

참고 사항 :
다른 많은 쿼리도 테이블 크기로 인해 완료하는 데 오랜 시간이 걸릴 것이라고 확신합니다. 스키마 설계에 대한 속도를 염두에두고 생각하면 성능 문제를 해결할 수 있습니다. 변경 옵션이 아니라고 말했지만 10 분 이상 쿼리가 옵션이 아니라는 것을 알 수 있습니다. 3 NF는 속도를 필요로하고, 기록하지 않는 경우 때로는 데이터가 여러 테이블에서 분할 될 수있을 때 항상 가장 좋은 방법은 아니다 함께 저장 될 수 있습니다. 생각해 볼 점 …


답변

다른 StackOverflow 질문 / 답변 에서이 스크립트를 얻었습니다.

SELECT SUM(p.rows) FROM sys.partitions AS p
  INNER JOIN sys.tables AS t
  ON p.[object_id] = t.[object_id]
  INNER JOIN sys.schemas AS s
  ON s.[schema_id] = t.[schema_id]
  WHERE t.name = N'YourTableNameHere'
  AND s.name = N'dbo'
  AND p.index_id IN (0,1);

내 테이블에는 5 억 개의 레코드가 있으며 위의 결과는 1ms 미만입니다. 그 동안에,

SELECT COUNT(id) FROM MyTable

39 분 52 초가 걸렸습니다!

그들은 정확히 같은 수의 행을 산출합니다 (제 경우에는 정확히 519326012).

나는 그것이 항상 그런 것인지 모른다.


답변

sp_spaceused (Transact-SQL)를 사용해 볼 수 있습니다

현재 데이터베이스의 테이블, 인덱싱 된 뷰 또는 Service Broker 큐에서 사용 된 행 수, 디스크 공간 및 디스크 공간을 표시하거나 전체 데이터베이스에서 예약 및 사용 된 디스크 공간을 표시합니다.


답변

SQL Server 버전이 2005/2008 인 경우 DMV를 사용하여 테이블의 행 수를 계산할 수 있습니다.

-- Shows all user tables and row counts for the current database 
-- Remove is_ms_shipped = 0 check to include system objects 
-- i.index_id < 2 indicates clustered index (1) or hash table (0) 
SELECT o.name,
 ddps.row_count
FROM sys.indexes AS i
 INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID
 INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID
 AND i.index_id = ddps.index_id
WHERE i.index_id < 2
 AND o.is_ms_shipped = 0
ORDER BY o.NAME 

SQL Server 2000 데이터베이스 엔진의 경우 sysindex가 작동하지만 조만간 제거 될 수 있으므로 이후 버전의 SQL Server에서는 사용하지 않는 것이 좋습니다.

샘플 코드 : 테이블 행 수를 신속하고 고통없이 얻는 방법