Tôi có một bảng trong cơ sở dữ liệu PostgreSQL được gọi là feeds_up
. Có vẻ như:Bản ghi gần đây nhất, trước ngày, theo danh mục: tối ưu hóa
| feed_url | isup | hasproblems | observed timestamp with tz | id (pk)|
|----------|------|-------------|-------------------------------|--------|
| http://b.| t | f | 2013-02-27 16:34:46.327401+11 | 15235 |
| http://f.| f | t | 2013-02-27 16:31:25.415126+11 | 15236 |
Nó có thứ gì đó giống như 300 nghìn hàng, tăng khoảng 20 hàng mỗi năm phút. Tôi có truy vấn chạy rất thường xuyên (mỗi lần tải trang)
select distinct on (feed_url) feed_url, isUp, hasProblems
from feeds_up
where observed <= '2013-02-27T05:38:00.000Z'
order by feed_url, observed desc;
Tôi đặt thời gian mẫu ở đó, thời gian đó được tham số. Phân tích giải thích là trên explain.depesz.com. Mất khoảng 8s. Khùng!
Chỉ có khoảng 20 giá trị duy nhất cho feed_url
, vì vậy điều này có vẻ thực sự không hiệu quả. Tôi nghĩ rằng tôi sẽ là ngu ngốc và thử một vòng lặp FOR trong một chức năng.
CREATE OR REPLACE FUNCTION feedStatusAtDate(theTime timestamp with time zone) RETURNS SETOF feeds_up AS
$BODY$
DECLARE
url feeds_list%rowtype;
BEGIN
FOR url IN SELECT * FROM feeds_list
LOOP
RETURN QUERY SELECT * FROM feeds_up
WHERE observed <= theTime
AND feed_url = url.feed_url
ORDER BY observed DESC LIMIT 1;
END LOOP;
END;
$BODY$ language plpgsql;
select * from feedStatusAtDate('2013-02-27T05:38:00.000Z');
Chỉ mất 307ms!
Sử dụng vòng lặp FOR trong SQL làm tôi hiểu sai, làm cách nào để tạo một truy vấn tốt đẹp — như truy vấn đầu tiên — hiệu quả? Điều đó có thể không? Hay đây là loại thứ mà vòng lặp FOR thực sự là tốt nhất?
ETA
Postgres phiên bản: PostgreSQL 9.1.5 trên i686-pc-linux-gnu, biên soạn bởi gcc (SUSE Linux) 4.3.4 [gcc-4_3-chi nhánh sửa đổi 152.973], 32-bit
Chỉ số trên feeds_up:
CREATE INDEX feeds_up_url
ON feeds_up
USING btree
(feed_url COLLATE pg_catalog."default");
CREATE INDEX feeds_up_url_observed
ON feeds_up
USING btree
(feed_url COLLATE pg_catalog."default", observed DESC);
CREATE INDEX feeds_up_observed
ON public.feeds_up
USING btree
(observed DESC);
Chỉ cần FYI @Cathy đã thử nâng cấp 'work_mem' lên 20MB với kết quả sau: http://explain.depesz.com/s/UJw (từ nhận xét về câu trả lời tôi đã xóa). Các loại không còn tràn vào đĩa nhưng truy vấn không phải là nhanh hơn đáng kể. Tạo một chỉ mục 'CREATE INDEX feeds_up_feed_url_observed ON feed_up (feed_url, DESC quan sát);' cũng không tốt; chỉ mục không được sử dụng. –
Phiên bản PostgreSQL nào, bằng cách này? 'SELECT version()'. –
@CraigRinger 9.1.5, tôi sẽ thực hiện chỉnh sửa. – Cathy