Tôi vừa xem lại một số mã cũ được viết cho trước PostgreSQL 8.4 và tôi đã thấy một cái gì đó thực sự tiện lợi. Tôi nhớ có một chức năng tùy chỉnh làm một số điều này trở lại trong ngày, nhưng tôi quên mất những gì array_agg()
trông giống như trước . Để xem xét, tổng hợp hiện đại được viết như thế này.
SELECT array_agg(x ORDER BY x DESC) FROM foobar;
Tuy nhiên, ngày xửa ngày xưa, nó được viết như thế này,
SELECT ARRAY(SELECT x FROM foobar ORDER BY x DESC);
Vì vậy, tôi đã thử nó với một số dữ liệu thử nghiệm ..
CREATE TEMP TABLE foobar AS
SELECT * FROM generate_series(1,1e7)
AS t(x);
Kết quả thật đáng ngạc nhiên .. Cách #OldSchoolCool đã nhanh hơn rất nhiều: tăng tốc 25%. Hơn nữa, đơn giản hóa nó mà không cần ĐẶT HÀNG, cho thấy sự chậm chạp tương tự.
# EXPLAIN ANALYZE SELECT ARRAY(SELECT x FROM foobar);
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Result (cost=104425.28..104425.29 rows=1 width=0) (actual time=1665.948..1665.949 rows=1 loops=1)
InitPlan 1 (returns $0)
-> Seq Scan on foobar (cost=0.00..104425.28 rows=6017728 width=32) (actual time=0.032..716.793 rows=10000000 loops=1)
Planning time: 0.068 ms
Execution time: 1671.482 ms
(5 rows)
test=# EXPLAIN ANALYZE SELECT array_agg(x) FROM foobar;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=119469.60..119469.61 rows=1 width=32) (actual time=2155.154..2155.154 rows=1 loops=1)
-> Seq Scan on foobar (cost=0.00..104425.28 rows=6017728 width=32) (actual time=0.031..717.831 rows=10000000 loops=1)
Planning time: 0.054 ms
Execution time: 2174.753 ms
(4 rows)
Vì vậy, những gì đang xảy ra ở đây. Tại sao Array_agg , một hàm nội bộ chậm hơn nhiều so với SQL voodoo của trình hoạch định?
Sử dụng " PostgreSQL 9.5.5 trên x86_64-pc-linux-gnu, được biên dịch bởi gcc (Ubuntu 6.2.0-5ubfox12) 6.2.0 20161005, 64-bit"
array_agg
phải theo dõi thứ tự của các đầu vào của nó trong đó hàmARRAY
tạo dường như đang làm một cái gì đó gần tương đương với mộtUNION
biểu thức bên trong. Nếu tôi phải mạo hiểm đoán,array_agg
có thể sẽ cần nhiều bộ nhớ hơn. Tôi không thể kiểm tra toàn diện điều này nhưng trên PostgreSQL 9.6 chạy trên Ubuntu 16.04,ARRAY()
truy vấn cóORDER BY
sử dụng hợp nhất bên ngoài và chậm hơnarray_agg
truy vấn. Như bạn đã nói, việc không đọc mã câu trả lời của bạn là lời giải thích tốt nhất mà chúng tôi có.