PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Pemesanan kueri lambat menurut kolom dalam tabel yang digabungkan

Kasus Uji

PostgreSQL 9.1. Uji basis data dengan sumber daya terbatas, tetapi cukup untuk kasus kecil ini. Lokal untuk pemeriksaan akan relevan:

SHOW LC_COLLATE;

 de_AT.UTF-8

Langkah 1) Rekonstruksi lingkungan pengujian mentah

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

Langkah 2) ANALISIS

    ANALYZE x.product;
    ANALYZE x.django_site;

Langkah 3) Susun ulang OLEH random()

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

ANALYZE x.p;

Hasil

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) Pra ANALISIS (-> pemindaian indeks bitmap)
2) Setelah ANALISIS (-> pemindaian seq)
3) Pesan ulang secara acak(), ANALISIS

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

1) Total waktu proses:1253.543 md
2) Total waktu proses:1250.351 md
3) Total waktu proses:1283.111 md

ORDER  BY p.ordering, p.name

1) Total waktu proses:177.266 md
2) Total waktu proses:174.556 md
3) Total waktu proses:177.797 md

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

1) Total runtime:176.628 md
2) Total runtime:176.811 md
3) Total runtime:178.150 md
Perencana jelas mempertimbangkan d.id bergantung secara fungsional.

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

1) Total waktu proses:242.218 md -- !!
2) Total waktu proses:245.234 md
3) Total waktu proses:254.581 md
Perencana jelas merindukan d.int_col . itu (NOT NULL) sama-sama bergantung secara fungsional. Tapi menyortir menurut kolom bilangan bulat itu murah.

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

1) Total waktu proses:2259.171 md -- !!
2) Total waktu proses:2257.650 md
3) Total waktu proses:2258.282 md
Mengurutkan berdasarkan varchar (panjang) atau text kolomnya mahal...

ORDER  BY p.name COLLATE "C"

1) Total waktu proses:327.516 md -- !!
2) Total waktu proses:325.103 md
3) Total waktu proses:327.206 md
... tapi tidak semahal jika dilakukan tanpa lokal.

Dengan tidak menggunakan lokal, urutkan berdasarkan varchar kolom tidak cukup tapi hampir secepat. Lokal "C" secara efektif "tidak ada lokal, hanya memesan berdasarkan nilai byte". Saya mengutip manualnya:

Jika Anda ingin sistem berperilaku seolah-olah tidak memiliki dukungan lokal, gunakan nama lokal khusus C, atau yang setara dengan POSIX.

Menyatukan semuanya, @dvd memilih:

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

...3) Total waktu proses:275.854 md
Seharusnya begitu.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Untuk mengabaikan kunci duplikat selama 'salin dari' di postgresql

  2. Cara Baru untuk Mempersonalisasi Pemantauan PostgreSQL Anda dengan Prometheus

  3. PostgreSQL - menonaktifkan batasan

  4. instal permata pg tidak berfungsi di OSX Lion

  5. Java SQL ERROR:Nama_Tabel Relasi tidak ada