PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Powolne porządkowanie zapytań według kolumny w połączonej tabeli

Przypadek testowy

PostgreSQL 9.1. Przetestuj bazę danych o ograniczonych zasobach, ale wystarczająco dla tego małego przypadku. Odpowiedni będzie język sortowania:

SHOW LC_COLLATE;

 de_AT.UTF-8

Krok 1) Zrekonstruuj surowe środowisko testowe

-- 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);

Krok 2) ANALIZA

    ANALYZE x.product;
    ANALYZE x.django_site;

Krok 3) Zmień kolejność BY random()

-- DROP TABLE x.p;
CREATE TABLE x.p AS
SELECT *
FROM   x.product
ORDER  BY random();

ANALYZE x.p;

Wyniki

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) ANALIZA WSTĘPNA (-> skanowanie indeksu bitmapy)
2) ANALIZA KOŃCOWA (-> skanowanie sekwencyjne)
3) Zmiana kolejności losowo(), ANALIZA

ORDER  BY d.domain, p.ordering, p.name

1) Całkowity czas pracy:1253.543 ms
2) Całkowity czas pracy:1250.351 ms
3) Całkowity czas pracy:1283.111 ms

ORDER  BY p.ordering, p.name

1) Całkowity czas pracy:177,266 ms
2) Całkowity czas pracy:174,556 ms
3) Całkowity czas pracy:177,797 ms

ORDER  BY d.id, p.ordering, p.name

1) Całkowity czas działania:176,628 ms
2) Całkowity czas działania:176,811 ms
3) Całkowity czas działania:178,150 ms
Planista oczywiście bierze pod uwagę ten d.id jest funkcjonalnie zależny.

ORDER  BY d.int_col, p.ordering, p.name -- integer column in other table

1) Całkowity czas pracy:242,218 ms -- !!
2) Całkowity czas pracy:245,234 ms
3) Całkowity czas pracy:254,581 ms
Plannerowi najwyraźniej brakuje tego d.int_col (NOT NULL) jest tak samo zależny funkcjonalnie. Ale sortowanie według kolumny liczb całkowitych jest tanie.

ORDER  BY p.name -- varchar(255) in same table

1) Całkowity czas pracy:2259.171 ms -- !!
2) Całkowity czas pracy:2257.650 ms
3) Całkowity czas pracy:2258.282 ms
Sortowanie według (długiego) varchar lub tekst kolumna jest droga...

ORDER  BY p.name COLLATE "C"

1) Całkowity czas pracy:327.516 ms -- !!
2) Całkowity czas pracy:325.103 ms
3) Całkowity czas pracy:327.206 ms
... ale nie tak drogie, jeśli zrobisz to bez lokalizacji.

Po usunięciu ustawień regionalnych, sortowanie według varchar kolumna nie jest całkiem, ale prawie tak samo szybka. Ustawienia regionalne "C" to w rzeczywistości „brak ustawień regionalnych, wystarczy uporządkować według wartości bajtów”. Cytuję instrukcję:

Jeśli chcesz, aby system zachowywał się tak, jakby nie miał obsługi lokalizacji, użyj specjalnej nazwy lokalizacji C lub równoważnej POSIX.

Podsumowując, @dvd wybrał:

ORDER  BY d.domain COLLATE "C", p.ordering, p.name

...3) Całkowity czas pracy:275,854 ms
To powinno wystarczyć.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL:Jak przekazać parametry z wiersza poleceń?

  2. Koncepcje Oracle High Availability w PostgreSQL

  3. Jak ukryć dekorację zestawu wyników w danych wyjściowych Psql?

  4. Schemat tworzenia PostgreSQL

  5. Wiele generatorów sekwencji Hibernate dla jednej jednostki z PostgreSQL