टेस्ट केस
पोस्टग्रेएसक्यूएल 9.1. सीमित संसाधनों के साथ डेटाबेस का परीक्षण करें, लेकिन इस छोटे से मामले के लिए पर्याप्त है। मिलान के लिए स्थान प्रासंगिक होगा:
SHOW LC_COLLATE;
de_AT.UTF-8
चरण 1) कच्चे परीक्षण वातावरण का पुनर्निर्माण करें
-- 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);
चरण 2) विश्लेषण करें
ANALYZE x.product;
ANALYZE x.django_site;
चरण 3) यादृच्छिक द्वारा पुन:क्रमित करें ()
-- DROP TABLE x.p;
CREATE TABLE x.p AS
SELECT *
FROM x.product
ORDER BY random();
ANALYZE x.p;
परिणाम
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) पूर्व विश्लेषण (-> बिटमैप इंडेक्स स्कैन)
2) विश्लेषण पोस्ट करें (-> seq स्कैन)
3) यादृच्छिक (), विश्लेषण
ORDER BY d.domain, p.ordering, p.name
1) कुल रनटाइम:1253.543 एमएस
2) कुल रनटाइम:1250.351 एमएस
3) कुल रनटाइम:1283.111 एमएस
ORDER BY p.ordering, p.name
1) कुल रनटाइम:177.266 एमएस
2) कुल रनटाइम:174.556 एमएस
3) कुल रनटाइम:177.797 एमएस
ORDER BY d.id, p.ordering, p.name
1) कुल रनटाइम:176.628 एमएस
2) कुल रनटाइम:176.811 एमएस
3) कुल रनटाइम:178.150 एमएस
नियोजक स्पष्ट रूप से उस d.idमें कारक हैं। कोड> कार्यात्मक रूप से निर्भर है।
ORDER BY d.int_col, p.ordering, p.name -- integer column in other table
1) कुल रनटाइम:242.218 एमएस -- !!
नियोजक स्पष्ट रूप से उस d.int_col
. को याद करता है (नल नहीं) कार्यात्मक रूप से निर्भर है। लेकिन एक पूर्णांक कॉलम के आधार पर छाँटना सस्ता है।
ORDER BY p.name -- varchar(255) in same table
1) कुल रनटाइम:2259.171 ms -- !!
2) कुल रनटाइम:2257.650 ms
3) कुल रनटाइम:2258.
एक (लंबे) varchar
by के आधार पर छँटाई या पाठ
कॉलम महंगा है ...
ORDER BY p.name COLLATE "C"
1) कुल रनटाइम:327.516 एमएस -- !!
... लेकिन अगर लोकेल के बिना किया जाए तो उतना महंगा नहीं है।
लोकेल के रास्ते से हटकर, एक varchar
. द्वारा छँटाई कॉलम काफी नहीं है लेकिन लगभग उतना ही तेज है। लोकेल "सी"
प्रभावी रूप से "कोई लोकेल नहीं है, बस बाइट वैल्यू द्वारा ऑर्डर करें"। मैं मैनुअल उद्धृत करता हूं:
यदि आप चाहते हैं कि सिस्टम ऐसा व्यवहार करे जैसे कि उसके पास कोई स्थानीय समर्थन नहीं है, तो विशेष लोकेल नाम C, या समान रूप से POSIX का उपयोग करें।
यह सब एक साथ रखकर, @dvd ने चुना:
ORDER BY d.domain COLLATE "C", p.ordering, p.name
...3) कुल रनटाइम:275.854 एमएस
ऐसा करना चाहिए।