PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Sắp xếp truy vấn chậm theo cột trong bảng đã nối

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm thế nào để chuyển đổi cơ sở dữ liệu postgres sang sqlite

  2. Ruby 'pg' gem liên kết đến bản sao sai của libpq.5.dylib (trên OSX)

  3. Psycopg2 sử dụng hết bộ nhớ trên truy vấn chọn lọc lớn

  4. Cách cài đặt PgBackRest

  5. Đối phó với các truy vấn chậm với PostgreSQL