MySQL - Sự khác biệt giữa việc sử dụng số đếm (*) và information_schema.tables để đếm hàng


15

Tôi muốn một cách nhanh chóng để đếm số lượng hàng trong bảng có vài triệu hàng. Tôi đã tìm thấy bài đăng " MySQL: Cách nhanh nhất để đếm số lượng hàng " trên Stack Overflow, có vẻ như nó sẽ giải quyết vấn đề của tôi. Bayuah cung cấp câu trả lời này:

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

Điều mà tôi thích bởi vì nó trông giống như một tra cứu thay vì quét, vì vậy nó sẽ nhanh, nhưng tôi quyết định thử nghiệm nó với

SELECT COUNT(*) FROM table 

để xem có bao nhiêu sự khác biệt về hiệu suất.

Thật không may, tôi nhận được câu trả lời khác nhau như dưới đây:

nhập mô tả hình ảnh ở đây

Câu hỏi

Tại sao các câu trả lời khác nhau khoảng 2 triệu hàng? Tôi đoán truy vấn thực hiện quét toàn bộ bảng là số chính xác hơn, nhưng có cách nào để tôi có thể lấy đúng số mà không phải chạy truy vấn chậm này không?


Tôi chạy ANALYZE TABLE data_302, hoàn thành trong 0,05 giây. Khi tôi chạy lại truy vấn, bây giờ tôi nhận được kết quả gần hơn với 34384599 hàng, nhưng nó vẫn không giống select count(*)với 34906061 hàng. Có phân tích bảng trả về ngay lập tức và xử lý trong nền? Tôi cảm thấy giá trị của nó đề cập đến đây là một cơ sở dữ liệu thử nghiệm và hiện không được viết cho.

Không ai quan tâm nếu đó chỉ là một trường hợp nói với ai đó về một cái bàn lớn như thế nào, nhưng tôi muốn chuyển số hàng cho một bit mã sẽ sử dụng hình đó để tạo một truy vấn không đồng bộ "có kích thước bằng nhau" để truy vấn cơ sở dữ liệu song song, tương tự như phương pháp được hiển thị trong Tăng hiệu năng truy vấn chậm với thực thi truy vấn song song của Alexander Rubin. Như vậy, tôi sẽ chỉ nhận được id cao nhất SELECT id from table_name order by id DESC limit 1và hy vọng các bảng của mình không bị phân mảnh quá nhiều.

Câu trả lời:


23

Có nhiều cách khác nhau để "đếm" các hàng trong một bảng. Điều gì là tốt nhất phụ thuộc vào các yêu cầu (độ chính xác của số đếm, tần suất được thực hiện, liệu chúng ta có cần đếm toàn bộ bảng hoặc với các biến wheregroup bymệnh đề, v.v.)

  • a) cách thông thường. Chỉ cần đếm chúng.

    select count(*) as table_rows from table_name ; 

    Độ chính xác : đếm chính xác 100% tại thời điểm truy vấn được chạy.
    Hiệu quả : Không tốt cho bàn lớn. (đối với các bảng MyISAM rất nhanh nhưng không ai sử dụng MyISAM trong những ngày này vì nó có quá nhiều nhược điểm so với InnoDB. "Nhanh chóng ngoạn mục" cũng chỉ áp dụng khi đếm các hàng của toàn bộ bảng MyISAM - nếu truy vấn có WHEREđiều kiện, thì nó sẽ có điều kiện vẫn phải quét bảng hoặc một chỉ mục.)
    Đối với các bảng InnoDB, nó phụ thuộc vào kích thước của bảng vì động cơ phải thực hiện quét toàn bộ bảng hoặc toàn bộ chỉ mục để có được số đếm chính xác. Bàn càng lớn thì càng chậm.

  • b) sử dụng SQL_CALC_FOUND_ROWSFOUND_ROWS(). Có thể được sử dụng thay vì cách trước, nếu chúng ta cũng muốn một số lượng nhỏ các hàng (thay đổi LIMIT). Tôi đã thấy nó được sử dụng để phân trang (để có được một số hàng và đồng thời biết tổng số int là bao nhiêu và tính số lượng pgegs).

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

    Độ chính xác : giống như trước đây.
    Hiệu quả : giống như trước đây.

  • c) sử dụng các information_schemabảng, như câu hỏi được liên kết:

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

    Độ chính xác : Chỉ là một xấp xỉ. Nếu bảng là mục tiêu của việc chèn và xóa thường xuyên, kết quả có thể giảm đi số lượng thực tế. Điều này có thể được cải thiện bằng cách chạy ANALYZE TABLEthường xuyên hơn.
    Hiệu quả : Rất tốt, nó hoàn toàn không chạm vào bàn.

  • d) lưu trữ số đếm trong cơ sở dữ liệu (trong bảng "bộ đếm" khác ) và cập nhật giá trị đó mỗi khi bảng có chèn, xóa hoặc cắt bớt (điều này có thể đạt được bằng cách kích hoạt hoặc bằng cách sửa đổi quy trình chèn và xóa) .
    Điều này tất nhiên sẽ đặt một tải bổ sung trong mỗi lần chèn và xóa nhưng sẽ cung cấp số đếm chính xác.

    Độ chính xác : đếm chính xác 100%.
    Hiệu quả : Rất tốt, chỉ cần đọc một hàng từ bảng khác.
    Tuy nhiên, nó đặt tải bổ sung vào cơ sở dữ liệu.

  • e) lưu trữ ( bộ nhớ đệm ) tính trong các lớp ứng dụng - và sử dụng phương pháp 1 (hoặc kết hợp các phương pháp trước đó). Ví dụ: chạy truy vấn đếm chính xác cứ sau 10 phút. Trong thời gian trung bình giữa hai lần đếm, hãy sử dụng giá trị được lưu trong bộ nhớ cache.

    Độ chính xác : gần đúng nhưng không quá tệ trong các trường hợp thông thường (trừ khi hàng ngàn hàng được thêm hoặc xóa).
    Hiệu quả : Rất tốt, giá trị luôn có sẵn.


1

Đối với INNODBbạn muốn information_schema.INNODB_SYS_TABLESTATS.NUM_ROWScho dữ liệu đếm hàng bảng chính xác, thay vì information_schema.TABLES.TABLE_ROWS.

Tôi đã đăng thêm chi tiết tại đây: /programming/33383877/why-does-inif-schema-tables-give-such-an-unurdy-answer-for-number-of-ro/49184843#49184843


1
Thông tin sai ... "Đối với INNODB, bạn muốn có thông tin_schema.INNODB_SYS_TABLESTATS.NUM_lawS cho hàng của bảng chính xác:" hướng dẫn rõ ràng nói về ước tính trên NUM_ROWScột
Raymond Nijland
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.