Trường hợp thử nghiệm
PostgreSQL 9.1. Kiểm tra cơ sở dữ liệu với tài nguyên hạn chế, nhưng đủ cho trường hợp nhỏ này. Ngôn ngữ để đối chiếu sẽ có liên quan:
SHOW LC_COLLATE;
de_AT.UTF-8
Bước 1) Xây dựng lại môi trường thử nghiệm thô
-- DROP TABLE x;
CREATE SCHEMA x; -- test schema
-- DROP TABLE x.django_site;
CREATE TABLE x.django_site (
id serial primary key
,domain character varying(100) not null
,int_col int not null
);
INSERT INTO x.django_site values (1,'www.testsite.com/foodir/', 3);
-- DROP TABLE x.product;
CREATE TABLE x.product (
id serial primary key
,site_id integer not null
,name character varying(255) not null
,slug character varying(255) not null
,sku character varying(255)
,ordering integer not null
,active boolean not null
);
INSERT INTO x.product (site_id, name, slug, sku, ordering, active)
SELECT 1
,repeat(chr((random() * 255)::int + 32), (random()*255)::int)
,repeat(chr((random() * 255)::int + 32), (random()*255)::int)
,repeat(chr((random() * 255)::int + 32), (random()*255)::int)
,i -- ordering in sequence
,NOT (random()* 0.5174346569119122)::int::bool
FROM generate_series(1, 17540) AS x(i);
-- SELECT ((591::float8 / 17540)* 0.5) / (1 - (591::float8 / 17540))
-- = 0.5174346569119122
CREATE INDEX product_site_id on x.product(site_id);
Bước 2) PHÂN TÍCH
ANALYZE x.product;
ANALYZE x.django_site;
Bước 3) Sắp xếp lại theo ngẫu nhiên ()
-- DROP TABLE x.p;
CREATE TABLE x.p AS
SELECT *
FROM x.product
ORDER BY random();
ANALYZE x.p;
Kết quả
EXPLAIN ANALYZE
SELECT p.*
FROM x.p
JOIN x.django_site d ON (p.site_id = d.id)
WHERE p.active
AND p.site_id = 1
-- ORDER BY d.domain, p.ordering, p.name
-- ORDER BY p.ordering, p.name
-- ORDER BY d.id, p.ordering, p.name
-- ORDER BY d.int_col, p.ordering, p.name
-- ORDER BY p.name COLLATE "C"
-- ORDER BY d.domain COLLATE "C", p.ordering, p.name -- dvd's final solution
1) PHÂN TÍCH trước (-> quét chỉ mục bitmap)
2) Đăng PHÂN TÍCH (-> quét seq)
3) Sắp xếp lại theo thứ tự ngẫu nhiên (), PHÂN TÍCH
ORDER BY d.domain, p.ordering, p.name
1) Tổng thời gian chạy:1253,543 ms
2) Tổng thời gian chạy:1250,351 ms
3) Tổng thời gian chạy:1283,111 ms
ORDER BY p.ordering, p.name
1) Tổng thời gian chạy:177,266 ms
2) Tổng thời gian chạy:174,556 ms
3) Tổng thời gian chạy:177,797 ms
ORDER BY d.id, p.ordering, p.name
1) Tổng thời gian chạy:176,628 ms
2) Tổng thời gian chạy:176,811 ms
3) Tổng thời gian chạy:178,150 ms
Trình lập kế hoạch rõ ràng là yếu tố trong đó d.id phụ thuộc về mặt chức năng.
ORDER BY d.int_col, p.ordering, p.name -- integer column in other table
1) Tổng thời gian chạy:242,188 ms - !!
2) Tổng thời gian chạy:245,234 ms
3) Tổng thời gian chạy: 254,581 ms
Người lập kế hoạch rõ ràng đã bỏ lỡ d.int_col
đó (NOT NULL) cũng phụ thuộc về mặt chức năng. Nhưng sắp xếp theo cột số nguyên là rẻ.
ORDER BY p.name -- varchar(255) in same table
1) Tổng thời gian chạy:2259,171 ms - !!
2) Tổng thời gian chạy:2257,650 ms
3) Tổng thời gian chạy: 2258,282 ms
Sắp xếp theo varchar
(dài) hoặc text
cột đắt ...
ORDER BY p.name COLLATE "C"
1) Tổng thời gian chạy:327,516 ms - !!
2) Tổng thời gian chạy:325,103 ms
3) Tổng thời gian chạy: 327,206 ms
... nhưng không đắt bằng nếu được thực hiện mà không có ngôn ngữ.
Không có ngôn ngữ, sắp xếp theo varchar
cột không phải là khá nhưng gần như là nhanh. Ngôn ngữ "C"
hiệu quả là "không có ngôn ngữ, chỉ cần sắp xếp theo giá trị byte". Tôi trích dẫn sách hướng dẫn:
Nếu bạn muốn hệ thống hoạt động như thể nó không có hỗ trợ ngôn ngữ, hãy sử dụng tên ngôn ngữ đặc biệt C hoặc tương đương là POSIX.
Tổng hợp tất cả lại với nhau, @dvd đã chọn:
ORDER BY d.domain COLLATE "C", p.ordering, p.name
... 3) Tổng thời gian chạy: 275,854 mili giây
Điều đó nên làm.