PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Cách nhanh chóng để khám phá số hàng của một bảng trong PostgreSQL

Đếm hàng trong các bảng lớn được biết là chậm trong PostgreSQL. Mô hình MVCC yêu cầu số lượng hàng trực tiếp đầy đủ để có một con số chính xác. Có những cách giải quyết để tăng tốc độ này lên đáng kể nếu số lượng không không phải chính xác giống như nó có vẻ như trong trường hợp của bạn.

(Hãy nhớ rằng ngay cả một số lượng "chính xác" cũng có thể chết khi đến nơi!)

Số lượng chính xác

Chậm cho các bảng lớn.
Với các thao tác ghi đồng thời, nó có thể lỗi thời ngay khi bạn nhận được.

SELECT count(*) AS exact_count FROM myschema.mytable;
Ước tính

Cực kỳ nhanh :

SELECT reltuples AS estimate FROM pg_class where relname = 'mytable';

Thông thường, ước tính là rất gần. Mức độ gần như thế nào, phụ thuộc vào việc ANALYZE hoặc VACUUM được chạy đủ - trong đó "đủ" được xác định bởi mức độ hoạt động ghi vào bảng của bạn.

Ước tính an toàn hơn

Phần trên bỏ qua khả năng có nhiều bảng có cùng tên trong một cơ sở dữ liệu - trong các lược đồ khác nhau. Để giải thích đ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';

Truyền tới bigint định dạng real số độc đáo, đặc biệt đối với số lượng lớn.

Ước tính tốt hơn

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 mã nhận dạng đối tượng.

Thay thế 'myschema.mytable'::regclass với to_regclass('myschema.mytable') trong Postgres 9.4+ để không nhận được gì thay vì một ngoại lệ cho các tên bảng không hợp lệ. Xem:

  • Cách kiểm tra xem một bảng có tồn tại trong một lược đồ nhất định không

Chưa có ước tính tốt hơn (với rất ít chi phí bổ sung)

Chúng tôi có thể làm những gì người lập kế hoạch Postgres làm. Trích dẫn Ví dụ về ước tính hàng trong sách hướng dẫn:

Những con số này hiện tại kể từ VACUUM cuối cùng hoặc ANALYZE trên bàn. Sau đó, trình lập kế hoạch tìm nạp số trang hiện tại thực tế trong bảng (đây là một thao tác rẻ, không yêu cầu quét bảng). Ifthat khác với relpages rồi đến reltuples được chia tỷ lệ theo tỷ lệ để đạt được ước tính số hàng hiện tại.

Postgres sử dụng estimate_rel_size được định nghĩa trong src/backend/utils/adt/plancat.c , cũng bao gồm trường hợp không có dữ liệu trong pg_class bởi vì mối quan hệ không bao giờ được hút chân không. Chúng ta có thể làm điều gì đó tương tự trong SQL:

Biểu mẫu tối thiểu

SELECT (reltuples / relpages * (pg_relation_size(oid) / 8192))::bigint
FROM   pg_class
WHERE  oid = 'mytable'::regclass;  -- your table here

An toàn và rõ ràng

SELECT (CASE WHEN c.reltuples < 0 THEN NULL       -- never vacuumed
             WHEN c.relpages = 0 THEN float8 '0'  -- empty table
             ELSE c.reltuples / c.relpages END
      * (pg_relation_size(c.oid) / pg_catalog.current_setting('block_size')::int)
       )::bigint
FROM   pg_class c
WHERE  c.oid = 'myschema.mytable'::regclass;      -- schema-qualified table here

Không bị vỡ với các bảng trống và bảng chưa từng thấy VACUUM hoặc ANALYZE . Hướng dẫn sử dụng pg_class :

Nếu bảng chưa bao giờ được hút chân không hoặc phân tích, hãy reltuples chứa -1 cho biết rằng số lượng hàng không xác định.

Nếu truy vấn này trả về NULL , chạy ANALYZE hoặc VACUUM cho bảng và lặp lại. (Ngoài ra, bạn có thể ước tính chiều rộng hàng dựa trên các loại cột như Postgres, nhưng điều đó tẻ nhạt và dễ xảy ra lỗi.)

Nếu truy vấn này trả về 0 , bàn có vẻ trống. Nhưng tôi sẽ ANALYZE để chắc chắn. (Và có thể kiểm tra autovacuum của bạn cài đặt.)

Thông thường, block_size là 8192. current_setting('block_size')::int bao gồm các trường hợp ngoại lệ hiếm hoi.

Mức độ bảng và giản đồ giúp nó miễn nhiễm với bất kỳ search_path nào và phạm vi.

Dù bằng cách nào, truy vấn luôn mất <0,1 mili giây đối với tôi.

Các tài nguyên Web khác:

  • Câu hỏi thường gặp về Postgres Wiki
  • Các trang wiki của Postgres dành cho ước tính số lượng và tính hiệu suất (*)

TABLESAMPLE SYSTEM (n) trong Postgres 9.5+

SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);

Giống như @a_horse đã nhận xét, mệnh đề được thêm vào cho SELECT lệnh có thể hữu ích nếu thống kê trong pg_class không đủ hiện tại vì một số lý do. Ví dụ:

  • Không có autovacuum đang chạy.
  • Ngay sau INSERT lớn / UPDATE / DELETE .
  • TEMPORARY bảng (không nằm trong autovacuum ).

Điều này chỉ xem xét một n ngẫu nhiên % (1 trong ví dụ) lựa chọn 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, thì số lượng sẽ thấp hơn bình thường, v.v.
  • Bộ giá trị đã chết hoặc một FILLFACTOR chiếm không gian mỗi khối. Nếu phân bổ không đồng đều trên bảng, ước tính có thể bị sai lệch.
  • Các lỗi làm tròn chung.

Thông thường, ướ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ố tiền lớn hơn một số hằng số được xác định trước,

Và liệu nó ...

... có thể xảy ra tại thời điểm số đếm vượt qua giá trị không đổi của tôi, nó sẽ dừng quá trình đếm (và không đợi kết thúc quá trình đếm để thông báo số lượng mũi tên lớn hơn).

Có. Bạn có thể sử dụng truy vấn con với LIMIT :

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 nhận được chính xác và hiện tại đếm cho đến n hàng (trong ví dụ là 500000) và n nếu không thì. Gần như không nhanh như ước tính trong pg_class , mặc dù.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chọn số hàng trong postgres

  2. Ổ cắm miền PostgreSQL UNIX so với ổ cắm TCP

  3. thiếu mục nhập mệnh đề FROM cho bảng Grupo cakephp

  4. Cách ánh xạ trường mảng PostgreSQL trong Django ORM

  5. 8 tính năng tương thích mới của Oracle trong EnterpriseDB PPAS 9.2 Beta