Đếm hàng trong các bảng lớn được biết là chậm trong PostgreSQL. Để có được một số chính xác, nó phải đếm đầy đủ các hàng do bản chất của MVCC . Có một cách để tăng tốc độ này lên một cách đáng kể nếu số lượng không không phải là chính xác như nó có vẻ là trong trường hợp của bạn.
Thay vì nhận được số lượng chính xác ( chậm với các bảng lớn):
SELECT count(*) AS exact_count FROM myschema.mytable;
Bạn nhận được một ước tính gần đúng như thế này ( cực kỳ nhanh ):
SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';
Ước tính gần đến mức nào phụ thuộc vào việc bạn chạy ANALYZE
đủ hay không. Nó thường rất gần.
Xem Câu hỏi thường gặp về Wiki PostgreSQL .
Hoặc trang wiki dành riêng cho hiệu suất đếm (*) .
Tốt hơn
Bài viết trên PostgreSQL Wiki được là một chút cẩu thả . Nó đã bỏ qua khả năng có thể có nhiều bảng cùng tên trong một cơ sở dữ liệu - trong các lược đồ khác nhau. Để giải thích cho điều đó:
SELECT c.reltuples::bigint AS estimate
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname = 'mytable'
AND n.nspname = 'myschema'
Hoặc tốt hơn vẫn là
SELECT reltuples::bigint AS estimate
FROM pg_class
WHERE oid = 'myschema.mytable'::regclass;
Nhanh hơn, đơn giản hơn, an toàn hơn, thanh lịch hơn. Xem hướng dẫn về Các loại Định danh Đối tượng .
Sử dụng to_regclass('myschema.mytable')
trong Postgres 9.4+ để tránh ngoại lệ cho tên bảng không hợp lệ:
SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);
Giống như @a_horse đã nhận xét , điều khoản mới được thêm vàoSELECT
lệnh có thể hữu ích nếu số liệu thống kê trong pg_class
không đủ hiện tại vì một số lý do. Ví dụ:
- Không
autovacuum
chạy.
- Ngay sau khi lớn
INSERT
hoặcDELETE
.
TEMPORARY
bảng (không được bao phủ bởi autovacuum
).
Điều này chỉ xem xét lựa chọn ngẫu nhiên n % ( 1
trong ví dụ) của các khối và đếm các hàng trong đó. Một mẫu lớn hơn làm tăng chi phí và giảm lỗi, lựa chọn của bạn. Độ chính xác phụ thuộc vào nhiều yếu tố hơn:
- Phân phối kích thước hàng. Nếu một khối nhất định xảy ra chứa các hàng rộng hơn bình thường, số lượng sẽ thấp hơn bình thường, v.v.
- Bộ giá trị chết hoặc
FILLFACTOR
chiếm không gian trên mỗi khối. Nếu phân bổ không đồng đều trên bảng, ước tính có thể bị lệch.
- Các lỗi làm tròn chung.
Trong hầu hết các trường hợp, ước tính từ pg_class
sẽ nhanh hơn và chính xác hơn.
Câu trả lời cho câu hỏi thực tế
Trước tiên, tôi cần biết số hàng trong bảng đó, nếu tổng số lớn hơn một số hằng số được xác định trước,
Và liệu nó ...
... có thể tại thời điểm số đếm vượt qua giá trị không đổi của tôi, nó sẽ dừng việc đếm (và không đợi kết thúc quá trình đếm để thông báo số hàng lớn hơn).
Đúng. Bạn có thể sử dụng một truy vấn con vớiLIMIT
:
SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;
Postgres thực sự ngừng đếm vượt quá giới hạn đã cho, bạn sẽ có được số lượng chính xác và hiện tại cho tối đa n hàng (trong ví dụ là 500000), còn n thì ngược lại. Tuy nhiên, gần như không nhanh như ước tính pg_class
.