Làm cách nào để tăng tốc ĐẶT HÀNG B BYNG cách sắp xếp khi sử dụng chỉ mục GIN trong PostgreSQL?


12

Tôi có một cái bàn như thế này:

CREATE TABLE products (
  id serial PRIMARY KEY, 
  category_ids integer[],
  published boolean NOT NULL,
  score integer NOT NULL,
  title varchar NOT NULL);

Một sản phẩm có thể thuộc nhiều loại. category_idscột chứa danh sách id của tất cả các danh mục sản phẩm.

Truy vấn điển hình trông như thế này (luôn tìm kiếm danh mục đơn):

SELECT * FROM products WHERE published
  AND category_ids @> ARRAY[23465]
ORDER BY score DESC, title
LIMIT 20 OFFSET 8000;

Để tăng tốc tôi sử dụng chỉ mục sau:

CREATE INDEX idx_test1 ON products
  USING GIN (category_ids gin__int_ops) WHERE published;

Điều này giúp rất nhiều trừ khi có quá nhiều sản phẩm trong một danh mục. Nó nhanh chóng lọc ra các sản phẩm thuộc danh mục đó nhưng sau đó có một thao tác sắp xếp phải được thực hiện một cách khó khăn (không có chỉ mục).

Một btree_gintiện ích mở rộng đã cài đặt cho phép tôi xây dựng chỉ mục GIN nhiều cột như thế này:

CREATE INDEX idx_test2 ON products USING GIN (
  category_ids gin__int_ops, score, title) WHERE published;

Nhưng Postgres không muốn sử dụng nó để sắp xếp . Ngay cả khi tôi loại bỏ DESCspecifier trong truy vấn.

Bất kỳ phương pháp thay thế để tối ưu hóa nhiệm vụ đều rất đáng hoan nghênh.


Thông tin thêm:

  • PostgreQuery 9.4, với phần mở rộng intarray
  • tổng số sản phẩm hiện tại là 260 nghìn nhưng dự kiến ​​sẽ tăng đáng kể (tối đa 10 triệu, đây là nền tảng thương mại điện tử nhiều khách thuê)
  • sản phẩm trên mỗi danh mục 1..10000 (có thể tăng tới 100 nghìn), trung bình dưới 100 nhưng những danh mục có số lượng sản phẩm lớn có xu hướng thu hút nhiều yêu cầu hơn

Kế hoạch truy vấn sau được lấy từ hệ thống kiểm tra nhỏ hơn (4680 sản phẩm trong danh mục đã chọn, tổng số sản phẩm 200 nghìn trong bảng):

Limit  (cost=948.99..948.99 rows=1 width=72) (actual time=82.330..82.341 rows=20 loops=1)
  ->  Sort  (cost=948.37..948.99 rows=245 width=72) (actual time=80.231..81.337 rows=4020 loops=1)
        Sort Key: score, title
        Sort Method: quicksort  Memory: 928kB
        ->  Bitmap Heap Scan on products  (cost=13.90..938.65 rows=245 width=72) (actual time=1.919..16.044 rows=4680 loops=1)
              Recheck Cond: ((category_ids @> '{292844}'::integer[]) AND published)
              Heap Blocks: exact=3441
              ->  Bitmap Index Scan on idx_test2  (cost=0.00..13.84 rows=245 width=0) (actual time=1.185..1.185 rows=4680 loops=1)
                    Index Cond: (category_ids @> '{292844}'::integer[])
Planning time: 0.202 ms
Execution time: 82.404 ms

Lưu ý # 1 : 82 ms có thể trông không đáng sợ nhưng đó là do bộ đệm sắp xếp phù hợp với bộ nhớ. Khi tôi chọn tất cả các cột từ bảng sản phẩm ( SELECT * FROM ...và trong thực tế có khoảng 60 cột), nó sẽ Sort Method: external merge Disk: 5696kBtăng gấp đôi thời gian thực hiện. Và đó chỉ là cho 4680 sản phẩm.

Điểm hành động số 1 (xuất phát từ Lưu ý số 1): Để giảm dung lượng bộ nhớ của hoạt động sắp xếp và do đó tăng tốc một chút, sẽ là khôn ngoan khi tìm nạp, sắp xếp và giới hạn id sản phẩm trước, sau đó tìm nạp các bản ghi đầy đủ:

SELECT * FROM products WHERE id IN (
  SELECT id FROM products WHERE published AND category_ids @> ARRAY[23465]
  ORDER BY score DESC, title LIMIT 20 OFFSET 8000
) ORDER BY score DESC, title;

Điều này đưa chúng tôi trở lại Sort Method: quicksort Memory: 903kBvà ~ 80 ms cho 4680 sản phẩm. Vẫn có thể chậm khi số lượng sản phẩm tăng lên 100k.


Trên trang này: hlinnaka.iki.fi/2014/03/28/ Có một nhận xét rằng btree_gin không thể được sử dụng để sắp xếp.
Mladen Uzelac

OK, tôi viết lại tiêu đề để cho phép nhiều lựa chọn hơn.
Yaroslav Stavnichiy

Bạn luôn tìm kiếm một danh mục duy nhất? Và vui lòng cung cấp một số thông tin cơ bản hơn: Phiên bản Postgres, cardinalality, hàng cho mỗi danh mục (tối thiểu / avg / max). xem xét hướng dẫn trong thông tin thẻ cho hiệu suất postgresql . Và: scorecó thể là NULL, nhưng bạn vẫn sắp xếp theo score DESC, không score DESC NULLS LAST. Một hoặc khác có vẻ không đúng ...
Erwin Brandstetter

Tôi đã thêm thông tin bổ sung theo yêu cầu. Tôi luôn luôn tìm kiếm cho thể loại duy nhất. Và scoretrên thực tế KHÔNG phải là NULL - Tôi đã sửa định nghĩa bảng.
Yaroslav Stavnichiy

Câu trả lời:


9

Tôi đã thực hiện rất nhiều thử nghiệm và đây là những phát hiện của tôi.

GIN và sắp xếp

Chỉ mục GIN hiện tại (kể từ phiên bản 9.4) không thể hỗ trợ đặt hàng .

Trong số các loại chỉ mục hiện đang được PostgreQuery hỗ trợ, chỉ có cây B có thể tạo đầu ra được sắp xếp - các loại chỉ mục khác trả về các hàng khớp với thứ tự không xác định, phụ thuộc vào việc triển khai.

làm việc

Cảm ơn Chris đã chỉ ra thông số cấu hình này . Nó mặc định là 4MB và trong trường hợp recordset của bạn lớn hơn, việc tăng work_memgiá trị phù hợp (có thể tìm thấy từ đó EXPLAIN ANALYSE) có thể tăng tốc đáng kể các hoạt động sắp xếp.

ALTER SYSTEM SET work_mem TO '32MB';

Khởi động lại máy chủ để thay đổi có hiệu lực, sau đó kiểm tra lại:

SHOW work_mem;

Truy vấn gốc

Tôi đã điền vào cơ sở dữ liệu của mình với 650k sản phẩm với một số danh mục chứa tới 40k sản phẩm. Tôi đã đơn giản hóa truy vấn một chút bằng cách xóa publishedmệnh đề:

SELECT * FROM products WHERE category_ids @> ARRAY [248688]
ORDER BY score DESC, title LIMIT 10 OFFSET 30000;

Limit  (cost=2435.62..2435.62 rows=1 width=1390) (actual time=1141.254..1141.256 rows=10 loops=1)
  ->  Sort  (cost=2434.00..2435.62 rows=646 width=1390) (actual time=1115.706..1140.513 rows=30010 loops=1)
        Sort Key: score, title
        Sort Method: external merge  Disk: 29656kB
        ->  Bitmap Heap Scan on products  (cost=17.01..2403.85 rows=646 width=1390) (actual time=11.831..25.646 rows=41666 loops=1)
              Recheck Cond: (category_ids @> '{248688}'::integer[])
              Heap Blocks: exact=6471
              ->  Bitmap Index Scan on idx_products_category_ids_gin  (cost=0.00..16.85 rows=646 width=0) (actual time=10.140..10.140 rows=41666 loops=1)
                    Index Cond: (category_ids @> '{248688}'::integer[])
Planning time: 0.288 ms
Execution time: 1146.322 ms

Như chúng ta có thể thấy work_memlà không đủ vì vậy chúng tôi đã có Sort Method: external merge Disk: 29656kB(con số ở đây là gần đúng, nó cần hơn 32 MB một chút cho quicksort trong bộ nhớ).

Giảm dung lượng bộ nhớ

Không chọn bản ghi đầy đủ để sắp xếp, sử dụng id, áp dụng sắp xếp, bù và giới hạn, sau đó tải chỉ 10 bản ghi chúng tôi cần:

SELECT * FROM products WHERE id in (
  SELECT id FROM products WHERE category_ids @> ARRAY[248688]
  ORDER BY score DESC, title LIMIT 10 OFFSET 30000
) ORDER BY score DESC, title;

Sort  (cost=2444.10..2444.11 rows=1 width=1390) (actual time=707.861..707.862 rows=10 loops=1)
  Sort Key: products.score, products.title
  Sort Method: quicksort  Memory: 35kB
  ->  Nested Loop  (cost=2436.05..2444.09 rows=1 width=1390) (actual time=707.764..707.803 rows=10 loops=1)
        ->  HashAggregate  (cost=2435.63..2435.64 rows=1 width=4) (actual time=707.744..707.746 rows=10 loops=1)
              Group Key: products_1.id
              ->  Limit  (cost=2435.62..2435.62 rows=1 width=72) (actual time=707.732..707.734 rows=10 loops=1)
                    ->  Sort  (cost=2434.00..2435.62 rows=646 width=72) (actual time=704.163..706.955 rows=30010 loops=1)
                          Sort Key: products_1.score, products_1.title
                          Sort Method: quicksort  Memory: 7396kB
                          ->  Bitmap Heap Scan on products products_1  (cost=17.01..2403.85 rows=646 width=72) (actual time=11.587..35.076 rows=41666 loops=1)
                                Recheck Cond: (category_ids @> '{248688}'::integer[])
                                Heap Blocks: exact=6471
                                ->  Bitmap Index Scan on idx_products_category_ids_gin  (cost=0.00..16.85 rows=646 width=0) (actual time=9.883..9.883 rows=41666 loops=1)
                                      Index Cond: (category_ids @> '{248688}'::integer[])
        ->  Index Scan using products_pkey on products  (cost=0.42..8.45 rows=1 width=1390) (actual time=0.004..0.004 rows=1 loops=10)
              Index Cond: (id = products_1.id)
Planning time: 0.682 ms
Execution time: 707.973 ms

Lưu ý Sort Method: quicksort Memory: 7396kB. Kết quả tốt hơn nhiều.

THAM GIA và chỉ số cây B bổ sung

Như Chris khuyên tôi đã tạo thêm chỉ mục:

CREATE INDEX idx_test7 ON products (score DESC, title);

Đầu tiên tôi đã thử tham gia như thế này:

SELECT * FROM products NATURAL JOIN
  (SELECT id FROM products WHERE category_ids @> ARRAY[248688]
  ORDER BY score DESC, title LIMIT 10 OFFSET 30000) c
ORDER BY score DESC, title;

Kế hoạch truy vấn khác nhau một chút nhưng kết quả là như nhau:

Sort  (cost=2444.10..2444.11 rows=1 width=1390) (actual time=700.747..700.747 rows=10 loops=1)
  Sort Key: products.score, products.title
  Sort Method: quicksort  Memory: 35kB
  ->  Nested Loop  (cost=2436.05..2444.09 rows=1 width=1390) (actual time=700.651..700.690 rows=10 loops=1)
        ->  HashAggregate  (cost=2435.63..2435.64 rows=1 width=4) (actual time=700.630..700.630 rows=10 loops=1)
              Group Key: products_1.id
              ->  Limit  (cost=2435.62..2435.62 rows=1 width=72) (actual time=700.619..700.619 rows=10 loops=1)
                    ->  Sort  (cost=2434.00..2435.62 rows=646 width=72) (actual time=697.304..699.868 rows=30010 loops=1)
                          Sort Key: products_1.score, products_1.title
                          Sort Method: quicksort  Memory: 7396kB
                          ->  Bitmap Heap Scan on products products_1  (cost=17.01..2403.85 rows=646 width=72) (actual time=10.796..32.258 rows=41666 loops=1)
                                Recheck Cond: (category_ids @> '{248688}'::integer[])
                                Heap Blocks: exact=6471
                                ->  Bitmap Index Scan on idx_products_category_ids_gin  (cost=0.00..16.85 rows=646 width=0) (actual time=9.234..9.234 rows=41666 loops=1)
                                      Index Cond: (category_ids @> '{248688}'::integer[])
        ->  Index Scan using products_pkey on products  (cost=0.42..8.45 rows=1 width=1390) (actual time=0.004..0.004 rows=1 loops=10)
              Index Cond: (id = products_1.id)
Planning time: 1.015 ms
Execution time: 700.918 ms

Chơi với nhiều độ lệch và số lượng sản phẩm khác nhau, tôi không thể khiến PostgreSQL sử dụng chỉ mục B-cây bổ sung.

Vì vậy, tôi đã đi theo cách cổ điển và tạo bảng ngã ba :

CREATE TABLE prodcats AS SELECT id AS product_id, unnest(category_ids) AS category_id FROM products;
CREATE INDEX idx_prodcats_cat_prod_id ON prodcats (category_id, product_id);

SELECT p.* FROM products p JOIN prodcats c ON (p.id=c.product_id)
WHERE c.category_id=248688
ORDER BY p.score DESC, p.title LIMIT 10 OFFSET 30000;

Limit  (cost=122480.06..122480.09 rows=10 width=1390) (actual time=1290.360..1290.362 rows=10 loops=1)
  ->  Sort  (cost=122405.06..122509.00 rows=41574 width=1390) (actual time=1264.250..1289.575 rows=30010 loops=1)
        Sort Key: p.score, p.title
        Sort Method: external merge  Disk: 29656kB
        ->  Merge Join  (cost=50.46..94061.13 rows=41574 width=1390) (actual time=117.746..182.048 rows=41666 loops=1)
              Merge Cond: (p.id = c.product_id)
              ->  Index Scan using products_pkey on products p  (cost=0.42..90738.43 rows=646067 width=1390) (actual time=0.034..116.313 rows=210283 loops=1)
              ->  Index Only Scan using idx_prodcats_cat_prod_id on prodcats c  (cost=0.43..1187.98 rows=41574 width=4) (actual time=0.022..7.137 rows=41666 loops=1)
                    Index Cond: (category_id = 248688)
                    Heap Fetches: 0
Planning time: 0.873 ms
Execution time: 1294.826 ms

Vẫn không sử dụng chỉ số cây B work_mem, kết quả không phù hợp , do đó kết quả kém.

Nhưng trong một số trường hợp, có số lượng lớn sản phẩmphần bù nhỏ PostgreSQL hiện quyết định sử dụng chỉ mục B-tree:

SELECT p.* FROM products p JOIN prodcats c ON (p.id=c.product_id)
WHERE c.category_id=248688
ORDER BY p.score DESC, p.title LIMIT 10 OFFSET 300;

Limit  (cost=3986.65..4119.51 rows=10 width=1390) (actual time=264.176..264.574 rows=10 loops=1)
  ->  Nested Loop  (cost=0.98..552334.77 rows=41574 width=1390) (actual time=250.378..264.558 rows=310 loops=1)
        ->  Index Scan using idx_test7 on products p  (cost=0.55..194665.62 rows=646067 width=1390) (actual time=0.030..83.026 rows=108037 loops=1)
        ->  Index Only Scan using idx_prodcats_cat_prod_id on prodcats c  (cost=0.43..0.54 rows=1 width=4) (actual time=0.001..0.001 rows=0 loops=108037)
              Index Cond: ((category_id = 248688) AND (product_id = p.id))
              Heap Fetches: 0
Planning time: 0.585 ms
Execution time: 264.664 ms

Điều này thực tế khá logic vì chỉ số cây B ở đây không tạo ra kết quả trực tiếp, nó chỉ được sử dụng như một hướng dẫn để quét tuần tự.

Hãy so sánh với truy vấn GIN:

SELECT * FROM products WHERE id in (
  SELECT id FROM products WHERE category_ids @> ARRAY[248688]
  ORDER BY score DESC, title LIMIT 10 OFFSET 300
) ORDER BY score DESC, title;

Sort  (cost=2519.53..2519.55 rows=10 width=1390) (actual time=143.809..143.809 rows=10 loops=1)
  Sort Key: products.score, products.title
  Sort Method: quicksort  Memory: 35kB
  ->  Nested Loop  (cost=2435.14..2519.36 rows=10 width=1390) (actual time=143.693..143.736 rows=10 loops=1)
        ->  HashAggregate  (cost=2434.71..2434.81 rows=10 width=4) (actual time=143.678..143.680 rows=10 loops=1)
              Group Key: products_1.id
              ->  Limit  (cost=2434.56..2434.59 rows=10 width=72) (actual time=143.668..143.670 rows=10 loops=1)
                    ->  Sort  (cost=2433.81..2435.43 rows=646 width=72) (actual time=143.642..143.653 rows=310 loops=1)
                          Sort Key: products_1.score, products_1.title
                          Sort Method: top-N heapsort  Memory: 68kB
                          ->  Bitmap Heap Scan on products products_1  (cost=17.01..2403.85 rows=646 width=72) (actual time=11.625..31.868 rows=41666 loops=1)
                                Recheck Cond: (category_ids @> '{248688}'::integer[])
                                Heap Blocks: exact=6471
                                ->  Bitmap Index Scan on idx_products_category_ids_gin  (cost=0.00..16.85 rows=646 width=0) (actual time=9.916..9.916 rows=41666 loops=1)
                                      Index Cond: (category_ids @> '{248688}'::integer[])
        ->  Index Scan using products_pkey on products  (cost=0.42..8.45 rows=1 width=1390) (actual time=0.004..0.004 rows=1 loops=10)
              Index Cond: (id = products_1.id)
Planning time: 0.630 ms
Execution time: 143.921 ms

Kết quả của GIN tốt hơn nhiều. Tôi đã kiểm tra với sự kết hợp khác nhau của số lượng sản phẩm và bù đắp, trong mọi trường hợp, cách tiếp cận bảng giao tiếp là tốt hơn .

Sức mạnh của chỉ số thực

Để PostgreSQL sử dụng đầy đủ chỉ mục để sắp xếp, tất cả các WHEREtham số truy vấn cũng như ORDER BYtham số phải nằm trong chỉ mục cây B duy nhất. Để làm điều này, tôi đã sao chép các trường sắp xếp từ sản phẩm sang bảng nối:

CREATE TABLE prodcats AS SELECT id AS product_id, unnest(category_ids) AS category_id, score, title FROM products;
CREATE INDEX idx_prodcats_1 ON prodcats (category_id, score DESC, title, product_id);

SELECT * FROM products WHERE id in (SELECT product_id FROM prodcats WHERE category_id=248688 ORDER BY score DESC, title LIMIT 10 OFFSET 30000) ORDER BY score DESC, title;

Sort  (cost=2149.65..2149.67 rows=10 width=1390) (actual time=7.011..7.011 rows=10 loops=1)
  Sort Key: products.score, products.title
  Sort Method: quicksort  Memory: 35kB
  ->  Nested Loop  (cost=2065.26..2149.48 rows=10 width=1390) (actual time=6.916..6.950 rows=10 loops=1)
        ->  HashAggregate  (cost=2064.83..2064.93 rows=10 width=4) (actual time=6.902..6.904 rows=10 loops=1)
              Group Key: prodcats.product_id
              ->  Limit  (cost=2064.02..2064.71 rows=10 width=74) (actual time=6.893..6.895 rows=10 loops=1)
                    ->  Index Only Scan using idx_prodcats_1 on prodcats  (cost=0.56..2860.10 rows=41574 width=74) (actual time=0.010..6.173 rows=30010 loops=1)
                          Index Cond: (category_id = 248688)
                          Heap Fetches: 0
        ->  Index Scan using products_pkey on products  (cost=0.42..8.45 rows=1 width=1390) (actual time=0.003..0.003 rows=1 loops=10)
              Index Cond: (id = prodcats.product_id)
Planning time: 0.318 ms
Execution time: 7.066 ms

Và đây là kịch bản tồi tệ nhất với số lượng lớn sản phẩm trong danh mục được chọn và bù đắp lớn. Khi bù = 300 thời gian thực hiện chỉ là 0,5 ms.

Thật không may, việc duy trì một bảng nối như vậy đòi hỏi nỗ lực thêm. Nó có thể được thực hiện thông qua các chế độ xem được lập chỉ mục, nhưng điều đó chỉ hữu ích khi hiếm khi cập nhật dữ liệu của bạn, vì làm mới chế độ xem được cụ thể hóa như vậy là một hoạt động khá nặng nề.

Vì vậy, tôi đang ở với chỉ số GIN cho đến nay, với work_memtruy vấn dấu chân bộ nhớ tăng và giảm.


Bạn không cần phải khởi động lại để thay đổi work_memcài đặt chung trong postgresql.conf. Tải lại là đủ. Và hãy để tôi cảnh báo không nên đặt work_memquá cao trên toàn cầu trong môi trường nhiều người dùng (cũng không quá thấp). Nếu bạn có một số truy vấn cần nhiều hơn work_mem, hãy đặt nó cao hơn cho phiên chỉ với SET- hoặc chỉ giao dịch với SET LOCAL. Xem: dba.stackexchange.com/a/48633/3684
Erwin Brandstetter

Thật là một câu trả lời tuyệt vời. Đã giúp tôi rất nhiều, cụ thể là với đĩa -> thao tác sắp xếp trong bộ nhớ, thay đổi nhanh chóng để giành chiến thắng tuyệt vời, cảm ơn!
Ricardo Villamil

4

Dưới đây là một vài mẹo nhanh có thể giúp cải thiện hiệu suất của bạn. Tôi sẽ bắt đầu với mẹo đơn giản nhất, gần như dễ dàng cho phần của bạn, và chuyển sang mẹo khó hơn sau lần đầu tiên.

1. work_mem

Vì vậy, tôi thấy ngay rằng một loại báo cáo trong kế hoạch giải thích của bạn Sort Method: external merge Disk: 5696kBđang tiêu thụ ít hơn 6 MB, nhưng đang tràn vào đĩa. Bạn cần tăng work_memcài đặt trong postgresql.conftệp của mình để đủ tuyệt vời để sắp xếp có thể vừa với bộ nhớ.

EDIT: Ngoài ra, khi kiểm tra thêm, tôi thấy rằng sau khi sử dụng chỉ mục để kiểm tra xem catgory_idscó phù hợp với tiêu chí của bạn không, việc quét chỉ mục bitmap buộc phải trở nên "mất mát" và phải kiểm tra lại điều kiện khi đọc các hàng từ trong các trang heap liên quan . Tham khảo bài đăng này trên postgresql.org để được giải thích tốt hơn tôi đã đưa ra. : P Điểm chính work_memlà cách của bạn quá thấp. Nếu bạn chưa điều chỉnh các cài đặt mặc định trên máy chủ của mình, nó sẽ không hoạt động tốt.

Khắc phục sự cố này sẽ khiến bạn không có thời gian để làm. Một thay đổi postgresql.conf, và bạn tắt! Tham khảo trang điều chỉnh hiệu suất này để biết thêm mẹo.

2. Thay đổi lược đồ

Vì vậy, bạn đã đưa ra quyết định trong thiết kế lược đồ của mình để không chuẩn hóa category_idsthành một mảng số nguyên, sau đó buộc bạn phải sử dụng chỉ mục GIN hoặc GIST để có quyền truy cập nhanh. Theo kinh nghiệm của tôi, việc bạn chọn chỉ số GIN sẽ nhanh hơn cho việc đọc so với GIST, vì vậy trong trường hợp đó bạn đã lựa chọn đúng. Tuy nhiên, GIN là một chỉ mục chưa được sắp xếp; nghĩ về nó giống như một chìa khóa-giá trị, nơi các vị từ bình đẳng là dễ dàng để kiểm tra, nhưng các hoạt động như WHERE >, WHERE <hoặc ORDER BYkhông được hỗ trợ bởi các chỉ số.

Một cách tiếp cận hợp lý sẽ là bình thường hóa thiết kế của bạn bằng cách sử dụng bảng cầu nối / bảng nối , được sử dụng để chỉ định các mối quan hệ nhiều-nhiều trong cơ sở dữ liệu.

Trong trường hợp này, bạn có nhiều danh mục và một tập hợp các số nguyên tương ứng category_idvà bạn có nhiều sản phẩm và product_ids tương ứng của chúng. Thay vì một cột trong bảng sản phẩm của bạn là một mảng số nguyên của category_ids, hãy xóa cột mảng này khỏi lược đồ của bạn và tạo một bảng dưới dạng

CREATE TABLE join_products_categories (product_id int, category_id int);

Sau đó, bạn có thể tạo các chỉ mục cây B trên hai cột của bảng cầu,

CREATE INDEX idx_products_in_join_table ON join_products_categories (product_id);
CREATE INDEX idx_products_in_join_table ON join_products_categories (category_id);

Chỉ là ý kiến ​​khiêm tốn của tôi, nhưng những thay đổi này có thể tạo ra sự khác biệt lớn cho bạn. Hãy thử work_memthay đổi điều đầu tiên, ít nhất là.

May mắn nhất!

BIÊN TẬP:

Xây dựng một chỉ mục bổ sung để hỗ trợ sắp xếp

Vì vậy, nếu theo thời gian dòng sản phẩm của bạn mở rộng, một số truy vấn nhất định có thể trả về nhiều kết quả (hàng nghìn, hàng chục nghìn?) Nhưng đó vẫn có thể chỉ là một tập hợp con nhỏ trong tổng số dòng sản phẩm của bạn. Trong những trường hợp này, việc sắp xếp thậm chí có thể khá tốn kém nếu được thực hiện trong bộ nhớ, nhưng một chỉ số được thiết kế phù hợp có thể được sử dụng để hỗ trợ sắp xếp.

Xem tài liệu chính thức của PostgreSQL mô tả Chỉ mục và ĐẶT HÀNG B .NG .

Nếu bạn tạo một chỉ mục phù hợp với ORDER BYyêu cầu của bạn

CREATE INDEX idx_product_sort ON products (score DESC, title);

sau đó Postgres sẽ tối ưu hóa và quyết định xem việc sử dụng chỉ mục hoặc thực hiện sắp xếp rõ ràng sẽ hiệu quả hơn về mặt chi phí. Hãy nhớ rằng không có gì đảm bảo rằng Postgres sẽ sử dụng chỉ mục; nó sẽ tìm cách tối ưu hóa hiệu suất và lựa chọn giữa việc sử dụng chỉ mục hoặc sắp xếp rõ ràng. Nếu bạn tạo chỉ mục này, hãy theo dõi nó để xem liệu nó có đang được sử dụng đủ để biện minh cho việc tạo ra nó hay không và loại bỏ nó nếu hầu hết các loại của bạn đang được thực hiện rõ ràng.

Tuy nhiên, tại thời điểm này, sự quan tâm lớn nhất của bạn có thể sẽ được sử dụng nhiều hơn work_mem , nhưng có những trường hợp chỉ số có thể hỗ trợ sắp xếp.


Tôi cũng đã suy nghĩ về việc sử dụng bảng nối để tránh GIN. Nhưng bạn đã không chỉ định làm thế nào sẽ giúp sắp xếp. Tôi nghĩ nó sẽ không giúp được gì. Tôi đã thử tham gia bảng sản phẩm với một bộ id sản phẩm được thu thập thông qua truy vấn GIN, mà tôi tin rằng nó khá giống với tham gia bạn đang cung cấp và hoạt động đó không thể sử dụng chỉ số b-cây về điểm số và tiêu đề. Có lẽ tôi xây dựng chỉ mục sai. Bạn có thể vui lòng giải thích về điều đó.
Yaroslav Stavnichiy

Xin lỗi, có lẽ tôi đã không giải thích rõ ràng đủ. Việc thay đổi work_memcấu hình của bạn nhằm khắc phục sự cố 'sắp xếp trên đĩa' cũng như vấn đề kiểm tra lại tình trạng của bạn. Khi số lượng sản phẩm tăng lên, bạn có thể cần phải có một chỉ mục bổ sung để sắp xếp. Xin vui lòng xem các chỉnh sửa của tôi ở trên để làm rõ.
Chris
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.