Postgres: đếm (*) so với đếm (id)


11

Tôi thấy trong tài liệu về sự khác biệt giữa count(*)count(pk). Tôi đã sử dụng count(pk)(nơi pka SERIAL PRIMARY KEY) không biết về sự tồn tại của count(*).

Câu hỏi của tôi là về tối ưu hóa nội bộ của Postgres. Có đủ thông minh để nhận ra rằng một SERIAL PRIMARY KEYsẽ tồn tại trong mỗi hàng và không bao giờ là sai và chỉ đếm các hàng hoặc nó sẽ thực hiện kiểm tra vị ngữ dự phòng cho mỗi hàng? Tôi đồng ý rằng điều này có lẽ là quá nhiều tối ưu hóa vô nghĩa nhưng tôi chỉ tò mò.

Tôi đã xem xét đầu ra của EXPLAINEXPLAIN VERBOSEcho count(*), count(id)count(id > 50)để xem nếu EXPLAINđề cập đến việc kiểm tra các vị từ trong đầu ra của nó. Nó không.

Câu trả lời:


15

Tôi nhận được kết quả phù hợp trong các thử nghiệm lặp đi lặp lại của tôi với các phiên bản khác nhau trong những năm qua:
count(*)hơi nhanh hơn count(pk). Nó cũng ngắn hơn và hầu hết thời gian phù hợp hơn với những gì được thử nghiệm: sự tồn tại của một hàng.

Liên quan:

Postgres có đủ thông minh để nhận ra rằng a SERIAL PRIMARY KEYsẽ tồn tại ở mọi hàng và không bao giờ là sai

Điều duy nhất có liên quan là sự NOT NULLràng buộc. Đây PRIMARY KEYNOT NULLtự động, serialhoặc never falselà trực giao cho câu hỏi.

Với count(col), nếu PostgreSQL đang cố gắng trở nên thông minh và kiểm tra danh mục hệ thống xem một cột có NOT NULLtrở lại tương đương hay không count(*), bạn vẫn sẽ có thêm một lần tra cứu trên bảng hệ thống so với count(*).

Đối với EXPLAINđầu ra, có một gợi ý:

EXPLAIN SELECT count(*) FROM ...

Aggregate  (cost=4963.38..4963.43 rows=1 width=0) ...


EXPLAIN SELECT count(pk) FROM ...

Aggregate  (cost=4963.38..4963.43 rows=1 width=4) ...

Có nghĩa là, count(col)được không chuyển đổi sang count(*), ngay cả khi nó được định nghĩa NOT NULL.


Đây vẫn là trường hợp với các phiên bản mới? Tôi nghĩ rằng nó sẽ không thực sự cần một tra cứu cho mọi truy vấn - nó có thể được lưu trữ.
Ondra ižka

1
Btw, với một NOT NULLcột, sự khác biệt là lớn nếu bạn có nhiều hàng. Trong trường hợp của chúng tôi với hàng triệu hàng, COUNT(*)nhanh hơn 3 lần. (Postgres 9.4)
Ondra ižka
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.