MySQL-count (*)와 information_schema.tables와 행 수 계산의 차이점


16

수백만 행이있는 테이블의 행 수를 계산하는 빠른 방법을 원합니다. 스택 오버플로에서 " MySQL : 행 수를 계산하는 가장 빠른 방법 "이라는 게시물을 찾았습니다 .이 문제가 해결되는 것처럼 보였습니다. Bayuah 가이 답변을 제공했습니다.

SELECT
    table_rows "Rows Count"
FROM
    information_schema.tables
WHERE
    table_name="Table_Name"
AND
    table_schema="Database_Name";

스캔 대신 조회처럼 보이기 때문에 마음에 들었으므로 빠르지 만 테스트를하기로 결정했습니다.

SELECT COUNT(*) FROM table 

성능 차이가 얼마나되는지 확인하십시오.

불행히도 아래와 같이 다른 답변 이 나타납니다.

여기에 이미지 설명을 입력하십시오

질문

답이 약 2 백만 행씩 다른 이유는 무엇입니까? 전체 테이블 스캔을 수행하는 쿼리가 더 정확한 숫자라고 생각하지만이 느린 쿼리를 실행하지 않고도 올바른 숫자를 얻을 수있는 방법이 있습니까?


나는 ANALYZE TABLE data_3020.05 초 안에 완료했다. 쿼리를 다시 실행하면 이제 34384599 행의 결과가 훨씬 가까워 지지만 34906061 행과 같은 숫자는 select count(*)아닙니다. 분석 테이블이 즉시 반환되고 백그라운드에서 처리됩니까? 나는 이것이 테스트 데이터베이스라고 언급 할 가치가 있다고 생각하며 현재 작성되지 않았습니다.

누군가에게 테이블의 크기를 알려주는 경우에 대해서는 아무도 신경 쓰지 않을 것입니다.하지만 행 수를 그 숫자를 사용하여 데이터베이스에 쿼리하는 "동일한 크기의"동기 쿼리를 만드는 코드에 비트 코드를 전달하고 싶었습니다. Alexander Rubin 의 병렬 쿼리 실행 으로 느린 쿼리 성능 향상에 나와있는 방법과 유사 하게 병렬로 수행 됩니다. 그대로, 나는 단지 가장 높은 id를 SELECT id from table_name order by id DESC limit 1얻고 테이블이 너무 조각화되지 않기를 바랍니다.

답변:


23

테이블에서 행을 "계산"하는 다양한 방법이 있습니다. 가장 좋은 것은 요구 사항 (횟수의 정확성, 수행 빈도, 전체 테이블 수 또는 변수 wheregroup by절 등이 필요한지 여부)에 따라 다릅니다 .

  • a) 정상적인 방법. 그냥 세어

    select count(*) as table_rows from table_name ; 

    정확도 : 쿼리 실행시 100 % 정확한 카운트
    효율성 : 큰 테이블에는 좋지 않습니다. (MyISAM 테이블의 경우 엄청나게 빠르지 만 요즘에는 InnoDB에 비해 많은 단점이 있기 때문에 아무도 MyISAM을 사용하지 않습니다. "스펙 틱하게 빠름" 은 전체 MyISAM 테이블의 행 수를 세는 경우에만 적용됩니다-쿼리에 WHERE조건이 있으면 여전히 테이블이나 인덱스를 스캔해야합니다.)
    InnoDB 테이블의 경우 정확한 카운트를 얻기 위해 엔진이 전체 테이블 또는 전체 인덱스를 스캔해야하므로 테이블의 크기에 따라 다릅니다. 테이블이 클수록 점점 느려집니다.

  • b)SQL_CALC_FOUND_ROWS 및 사용 FOUND_ROWS(). 적은 수의 행을 원할 경우 이전 방법 대신 사용할 수 있습니다 ( LIMIT). 페이징에 사용되는 것을 보았습니다 (일부 행을 가져오고 동시에 총 수를 알고 pgegs 수를 계산하는 경우).

    select sql_calc_found_rows * from table_name limit 0 ; 
    select found_rows() as table_rows ;

    정확도 : 이전과 동일합니다.
    효율성 : 이전과 동일합니다.

  • c)information_schema 관련 질문으로 표를 사용 :

    select  table_rows
    from    information_schema.tables
    where   table_schema = 'database_name'
      and   table_name = 'table_name' ;

    정확도 : 근사치입니다. 테이블이 빈번한 삽입 및 삭제의 대상인 경우 결과는 실제 수에서 벗어날 수 있습니다. ANALYZE TABLE더 자주 실행하면 개선 할 수 있습니다 .
    효율성 : 아주 좋으며 테이블에 전혀 닿지 않습니다.

  • d) 데이터베이스에 카운트를 저장하고 (다른 "카운터"테이블에 ) 테이블에 삽입, 삭제 또는 잘라내 기가있을 때마다 해당 값을 업데이트하십시오 (트리거를 사용하거나 삽입 및 삭제 프로 시저를 수정하여 수행 할 수 있음) .
    이것은 물론 각 인서트에 추가 하중을 가하고 삭제하지만 정확한 카운트를 제공합니다.

    정확도 : 100 % 정확한 카운트.
    효율성 : 매우 좋고 다른 테이블에서 단일 행만 읽으면됩니다.
    그러나 데이터베이스에 추가로드가 발생합니다.

  • e) 애플리케이션 계층에 카운트를 저장 ( 캐싱 )하고-첫 번째 방법 (또는 이전 방법의 조합)을 사용합니다. 예 : 10 분마다 정확한 개수 쿼리를 실행하십시오. 두 카운트 사이의 평균 시간에는 캐시 된 값을 사용하십시오.

    정확도 : 근사 환경에서는 근사치이지만 너무 나쁘지는 않습니다 (수천 행이 추가되거나 삭제되지 않는 한).
    효율성 : 아주 좋습니다. 값을 항상 사용할 수 있습니다.


1

들어 INNODB당신이 원하는 information_schema.INNODB_SYS_TABLESTATS.NUM_ROWS대신, 정확한 테이블 행 카운트 데이터 information_schema.TABLES.TABLE_ROWS.

자세한 내용은 여기에 게시하십시오 : https : //.com/questions/33383877/why-does-information-schema-tables-give-such-an-unstable-answer-for-number-of-ro/49184843#49184843


1
잘못된 정보 ... "INNODB 위해 당신은 정확한 테이블 행에 대한 information_schema.INNODB_SYS_TABLESTATS.NUM_ROWS를 원한다" 매뉴얼이 명확하게 말한다 추정NUM_ROWS콜 럼
레이몬드 Nijland을
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.