Tôi đang thực hiện một bản cập nhật trong đó tôi yêu cầu một đẳng thức chính xác trên một tstzrange
biến. ~ 1M hàng được sửa đổi và truy vấn mất ~ 13 phút. Kết quả EXPLAIN ANALYZE
có thể được nhìn thấy ở đây và kết quả thực tế rất khác so với kết quả được ước tính bởi trình hoạch định truy vấn. Vấn đề là quét chỉ mục trên t_range
mong đợi một hàng duy nhất được trả về.
Điều này dường như có liên quan đến thực tế là số liệu thống kê về các loại phạm vi được lưu trữ khác với các loại khác. Nhìn vào pg_stats
xem cho cột, n_distinct
là -1 và các lĩnh vực khác (ví dụ most_common_vals
, most_common_freqs
) là rỗng.
Tuy nhiên, phải có số liệu thống kê được lưu trữ ở t_range
đâu đó. Một bản cập nhật cực kỳ giống nhau khi tôi sử dụng 'trong' trên t_range thay vì một đẳng thức chính xác mất khoảng 4 phút để thực hiện và sử dụng một kế hoạch truy vấn khác biệt đáng kể (xem tại đây ). Kế hoạch truy vấn thứ hai có ý nghĩa với tôi bởi vì mỗi hàng trong bảng tạm thời và một phần đáng kể của bảng lịch sử sẽ được sử dụng. Quan trọng hơn, trình hoạch định truy vấn dự đoán số lượng hàng chính xác cho bộ lọc trên t_range
.
Sự phân phối của t_range
một chút khác thường. Tôi đang sử dụng bảng này để lưu trữ trạng thái lịch sử của một bảng khác và các thay đổi đối với bảng khác xảy ra cùng một lúc trong các bãi lớn, do đó không có nhiều giá trị khác biệt t_range
. Dưới đây là số lượng tương ứng với từng giá trị duy nhất của t_range
:
t_range | count
-------------------------------------------------------------------+---------
["2014-06-12 20:58:21.447478+00","2014-06-27 07:00:00+00") | 994676
["2014-06-12 20:58:21.447478+00","2014-08-01 01:22:14.621887+00") | 36791
["2014-06-27 07:00:00+00","2014-08-01 07:00:01+00") | 1000403
["2014-06-27 07:00:00+00",infinity) | 36791
["2014-08-01 07:00:01+00",infinity) | 999753
Tổng số cho các khác biệt t_range
ở trên đã hoàn tất, do đó, số lượng thẻ là ~ 3M (trong đó ~ 1M sẽ bị ảnh hưởng bởi một trong hai truy vấn cập nhật).
Tại sao truy vấn 1 thực hiện kém hơn nhiều so với truy vấn 2? Trong trường hợp của tôi, truy vấn 2 là một thay thế tốt, nhưng nếu một sự bình đẳng phạm vi chính xác thực sự được yêu cầu, làm thế nào tôi có thể khiến Postgres sử dụng một kế hoạch truy vấn thông minh hơn?
Định nghĩa bảng với các chỉ mục (bỏ các cột không liên quan):
Column | Type | Modifiers
---------------------+-----------+------------------------------------------------------------------------------
history_id | integer | not null default nextval('gtfs_stop_times_history_history_id_seq'::regclass)
t_range | tstzrange | not null
trip_id | text | not null
stop_sequence | integer | not null
shape_dist_traveled | real |
Indexes:
"gtfs_stop_times_history_pkey" PRIMARY KEY, btree (history_id)
"gtfs_stop_times_history_t_range" gist (t_range)
"gtfs_stop_times_history_trip_id" btree (trip_id)
Truy vấn 1:
UPDATE gtfs_stop_times_history sth
SET shape_dist_traveled = tt.shape_dist_traveled
FROM gtfs_stop_times_temp tt
WHERE sth.trip_id = tt.trip_id
AND sth.stop_sequence = tt.stop_sequence
AND sth.t_range = '["2014-08-01 07:00:01+00",infinity)'::tstzrange;
Truy vấn 2:
UPDATE gtfs_stop_times_history sth
SET shape_dist_traveled = tt.shape_dist_traveled
FROM gtfs_stop_times_temp tt
WHERE sth.trip_id = tt.trip_id
AND sth.stop_sequence = tt.stop_sequence
AND '2014-08-01 07:00:01+00'::timestamptz <@ sth.t_range;
Q1 cập nhật 999753 hàng và cập nhật Q2 999753 + 36791 = 1036544 (nghĩa là bảng tạm thời sao cho mọi hàng khớp với điều kiện phạm vi thời gian được cập nhật).
Tôi đã thử truy vấn này để phản hồi bình luận của @ ypercube :
Truy vấn 3:
UPDATE gtfs_stop_times_history sth
SET shape_dist_traveled = tt.shape_dist_traveled
FROM gtfs_stop_times_temp tt
WHERE sth.trip_id = tt.trip_id
AND sth.stop_sequence = tt.stop_sequence
AND sth.t_range <@ '["2014-08-01 07:00:01+00",infinity)'::tstzrange
AND '["2014-08-01 07:00:01+00",infinity)'::tstzrange <@ sth.t_range;
Kế hoạch truy vấn và kết quả (xem tại đây ) là trung gian giữa hai trường hợp trước (~ 6 phút).
2016/02/05 CHỈNH SỬA
Không còn có quyền truy cập vào dữ liệu sau 1,5 năm, tôi đã tạo một bảng thử nghiệm có cùng cấu trúc (không có chỉ mục) và tính chính xác tương tự. Câu trả lời của jjanes đề xuất rằng nguyên nhân có thể là thứ tự của bảng tạm thời được sử dụng để cập nhật. Tôi không thể kiểm tra giả thuyết trực tiếp vì tôi không có quyền truy cập track_io_timing
(sử dụng Amazon RDS).
Kết quả tổng thể nhanh hơn nhiều (theo hệ số vài). Tôi đoán rằng điều này là do việc loại bỏ các chỉ số, phù hợp với câu trả lời của Erwin .
Trong trường hợp thử nghiệm này, Truy vấn 1 và 2 về cơ bản mất cùng một lượng thời gian, vì cả hai đều sử dụng phép nối hợp nhất. Đó là, tôi không thể kích hoạt bất cứ điều gì khiến Postgres chọn tham gia băm, vì vậy tôi không rõ tại sao Postgres lại chọn tham gia băm hoạt động kém ở nơi đầu tiên.
(lower(t_range),upper(t_range))
kể từ khi bạn kiểm tra sự bình đẳng.
(a = b)
thành hai điều kiện "chứa" :(a @> b AND b @> a)
? Liệu kế hoạch thay đổi?