PostgreSQL'de GIN dizini kullanılırken ORDER BY sıralama nasıl hızlandırılır?


13

Ben böyle bir tablo var:

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

Bir ürün birden fazla kategoriye ait olabilir. category_idssütununda, tüm ürün kategorilerinin kimliklerinin bir listesi bulunur.

Tipik sorgu şuna benzer (her zaman tek bir kategori arar):

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

Hızlandırmak için aşağıdaki dizini kullanıyorum:

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

Bu, bir kategoride çok fazla ürün olmadığı sürece çok yardımcı olur. Bu kategoriye ait ürünleri hızlı bir şekilde filtreler, ancak daha sonra zor yoldan yapılması gereken bir sıralama işlemi vardır (dizinsiz).

Bu gibi btree_ginçok sütunlu GIN dizini oluşturmama izin veren bir yüklü uzantı var :

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

Ancak Postgres bunu sıralama için kullanmak istemiyor . DESCSorgudaki belirleyiciyi kaldırdığımda bile .

Görevi optimize etmek için herhangi bir alternatif yaklaşım çok açıktır.


Ek bilgi:

  • Intarray uzatmalı PostgreSQL 9.4
  • şu anda toplam ürün sayısı 260 bin, ancak önemli ölçüde büyümesi bekleniyor (10 milyona kadar, bu çok kiracılı e-ticaret platformudur)
  • kategori başına ürünler 1.10000 (100k'ye kadar büyüyebilir), ortalama 100'ün altındadır, ancak çok sayıda ürüne sahip kategoriler daha fazla istek çekme eğilimindedir

Aşağıdaki sorgu planı daha küçük test sisteminden elde edilmiştir (seçilen kategorideki 4680 ürün, tabloda toplam 200 bin ürün):

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

Not # 1 : 82 ms bu kadar korkutucu görünmeyebilir, ancak bunun nedeni sıralama arabelleğinin belleğe sığmasıdır. Ürünler tablosundan tüm sütunları seçtiğimde ( SELECT * FROM ...ve gerçek hayatta yaklaşık 60 sütun var) Sort Method: external merge Disk: 5696kByürütme süresini iki katına çıkarır. Ve bu sadece 4680 ürün içindir.

Eylem noktası # 1 (Not # 1'den gelir): Sıralama işleminin bellek ayak izini azaltmak ve bu nedenle biraz hızlandırmak için önce ürün kimliklerini almak, sıralamak ve sınırlamak, ardından tam kayıtları almak akıllıca olacaktır:

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;

Bu bizi Sort Method: quicksort Memory: 903kB4680 ürün için ~ 80 ms'ye geri getiriyor . Ürün sayısı 100 bin'e ulaştığında hala yavaş olabilir.


Bu sayfada: hlinnaka.iki.fi/2014/03/28/… btree_gin'in sıralama için kullanılamayacağı yönünde bir yorum var.
Mladen Uzelac

Tamam, daha fazla seçeneğe izin vermek için başlığı yeniden yazdım.
Yaroslav Stavnichiy

Her zaman tek bir kategori mi arıyorsunuz? Ve lütfen biraz daha temel bilgi verin: Postgres sürümü, kardinaliteler, kategori başına satır (min / avg / max). postgresql-performance için etiket bilgisindeki talimatları dikkate alın . Ve: scoreNULL olabilir, ama yine de sıralayabilirsiniz score DESC, değil score DESC NULLS LAST. Biri ya da diğeri doğru değil ...
Erwin Brandstetter

İstendiği gibi ek bilgi ekledim. Her zaman tek bir kategori arıyorum. Ve scoreaslında NULL DEĞİL - tablo tanımını düzelttim.
Yaroslav Stavnichiy

Yanıtlar:


10

Çok fazla deneme yaptım ve işte bulgularım.

GIN ve sıralama

Şu anda GIN dizini (sürüm 9.4'ten itibaren) sipariş vermeye yardımcı olamaz .

Şu anda PostgreSQL tarafından desteklenen dizin türlerinden yalnızca B-ağacı sıralı çıktı üretebilir - diğer dizin türleri eşleşen satırları belirtilmemiş, uygulamaya bağlı bir sırayla döndürür.

work_mem

Chris, bu yapılandırma parametresini işaret ettiği için teşekkürler . Varsayılan olarak 4MB'dir ve kayıt kümeniz daha büyükse, work_memuygun değere (bulunabilir EXPLAIN ANALYSE) ulaşmak, sıralama işlemlerini önemli ölçüde hızlandırabilir.

ALTER SYSTEM SET work_mem TO '32MB';

Değişikliklerin etkili olması için sunucuyu yeniden başlatın, ardından iki kez kontrol edin:

SHOW work_mem;

Orijinal sorgu

Veritabanımı 650 bin ürünle doldurdum, bazı kategoriler 40 bin ürün tutuyordu. Yan tümceyi kaldırarak sorguyu biraz basitleştirdim published:

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

Gördüğümüz gibi work_memyeterli değildi Sort Method: external merge Disk: 29656kB(buradaki sayı yaklaşıktır, bellek içi quicksort için 32MB'den biraz daha fazlasına ihtiyaç duyar).

Bellek ayak izini azaltın

Sıralama için tam kayıt seçmeyin, kimlikleri kullanmayın, sıralama, ofset ve sınır uygulayın, ardından ihtiyacımız olan yalnızca 10 kayıt yükleyin:

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

Not Sort Method: quicksort Memory: 7396kB. Sonuç çok daha iyi.

JOIN ve ek B-ağacı dizini

Chris'in önerdiği gibi ek dizin oluşturdum:

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

Önce böyle katılmaya çalıştım:

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;

Sorgu planı biraz farklılık gösterir ancak sonuç aynıdır:

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

Çeşitli ofsetler ve ürün sayılarıyla oynamak PostgreSQL'in ek B-ağacı indeksi kullanmasını sağlayamadım.

Böylece klasik yollara gittim ve birleşme tablosu oluşturdum :

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

Hâlâ B-ağacı indeksi kullanılmıyorsa, work_memsonuç kümesi uymuyor , bu nedenle kötü sonuçlar elde ediliyor .

Ancak bazı durumlarda, çok sayıda ürüne ve küçük ofsete sahip PostgreSQL artık B-ağacı dizinini kullanmaya karar veriyor:

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

Buradaki B-ağacı endeksi doğrudan sonuç üretmediği için bu oldukça mantıklıdır, sadece sıralı tarama için bir kılavuz olarak kullanılır.

GIN sorgusuyla karşılaştıralım:

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

GIN'in sonucu çok daha iyi. Çeşitli ürün ve ofset kombinasyonları ile kontrol ettim, hiçbir koşulda bağlantı tablosu yaklaşımı daha iyi değildi .

Reel endeksin gücü

PostgreSQL'in sıralama için dizini tam olarak kullanabilmesi için, tüm sorgu WHEREparametrelerinin yanı sıra ORDER BYparametrelerin tek B-ağacı dizininde bulunması gerekir. Bunu yapmak için sıralama alanlarını üründen bağlantı tablosuna kopyaladım:

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

Ve bu, seçilen kategoride çok sayıda ürün ve büyük ofset ile en kötü senaryodur. Ofset = 300 yürütme süresi sadece 0,5 ms olduğunda.

Ne yazık ki böyle bir kavşak tablosunun bakımı ekstra çaba gerektirir. İndekslenmiş materyalize görünümler yoluyla gerçekleştirilebilir, ancak bu yalnızca verileriniz nadiren güncellendiğinde yararlıdır, bu tür materyalize görünümün yenilenmesine neden oldukça ağır bir işlemdir.

Bu yüzden şimdiye kadar GIN endeksi ile artan work_memve azaltılmış bellek ayak izi sorgusu ile kalıyorum .


Sen do not gerek yeniden başlatma genel değişikliği için work_mempostgresql.conf ayarında. Yeniden yükleme yeterlidir. Ve work_memçok kullanıcılı bir ortamda (çok düşük değil) küresel olarak çok yüksek ayarlamaya karşı uyarmama izin verin . Daha fazlasına ihtiyaç duyan bazı sorularınız varsa work_mem, oturum için yalnızca SET- veya yalnızca işlemle daha yüksek bir değere ayarlayın SET LOCAL. Bakınız: dba.stackexchange.com/a/48633/3684
Erwin Brandstetter

Ne harika bir cevap. Özellikle disk ile bana çok yardımcı oldu -> bellek içi sıralama işlemi, büyük bir kazanç için hızlı değişim, teşekkürler!
Ricardo Villamil

4

Performansınızı artırmanıza yardımcı olabilecek birkaç hızlı ipucu. Senin için neredeyse zahmetsiz olan en kolay ipucu ile başlayacağım ve ilkinden sonra daha zor ipucuna geçeceğim.

1. work_mem

Yani, açıklama planınızda bildirilen bir türün Sort Method: external merge Disk: 5696kB6 MB'den daha az tükettiğini, ancak diske döktüğünü görüyorum . Sıralamanın belleğe sığabileceği kadar büyük olması work_memiçin postgresql.confdosyanızdaki ayarınızı artırmanız gerekir .

DÜZENLEME: Ayrıca, daha fazla denetimde, catgory_idsölçütlerinize uygun olup olmadığını kontrol etmek için dizini kullandıktan sonra , bitmap dizin taramasının "kayıplı" olmaya zorlandığını ve ilgili yığın sayfalarındaki satırları okurken durumu yeniden kontrol etmesi gerektiğini görüyorum . Verdiğimden daha iyi bir açıklama için postgresql.org adresindeki bu gönderiye bakın . : P Ana nokta senin work_memçok düşük olmasıdır. Sunucunuzdaki varsayılan ayarları ayarlamadıysanız, iyi performans göstermeyecektir.

Bu düzeltme, size esasen zaman ayırmayacaktır. Bir değişiklik postgresql.confyaparsanız ve işiniz biter! Daha fazla ipucu için bu performans ayarlama sayfasına bakın .

2. Şema değişikliği

Böylece, şema tasarımınızda category_idsbir tamsayı dizisine denormalize etme kararı aldınız , bu da sizi hızlı erişim elde etmek için bir GIN veya GIST dizini kullanmaya zorlar. Deneyimlerime göre, bir GIN dizini seçiminiz okumalar için bir GIST'den daha hızlı olacaktır, bu durumda doğru seçimi yaptınız. Ancak, GIN sıralanmamış bir dizindir; daha bir eşitlik yüklemler kontrol etmek kolaydır anahtar değeri, fakat gibi operasyonların gibi düşünmeye WHERE >, WHERE <ya da ORDER BYdizine göre kolaylaştırdı değildir.

İyi bir yaklaşım , veritabanlarında çoktan çoğa ilişkileri belirtmek için kullanılan bir köprü tablosu / bağlantı tablosu kullanarak tasarımınızı normalleştirmek olacaktır .

Bu durumda, birçok kategoriniz ve buna karşılık gelen tamsayılar kümeniz category_idvar ve birçok ürününüz ve bunların karşılık gelen product_ids'leri var. Ürün tablonuzda category_ids tamsayı dizisi olan bir sütun yerine, bu dizi sütununu şemanızdan kaldırın ve aşağıdaki gibi bir tablo oluşturun

CREATE TABLE join_products_categories (product_id int, category_id int);

Ardından, köprü tablosunun iki sütununda B-ağacı indeksleri oluşturabilirsiniz,

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

Sadece alçakgönüllü görüşüm, ancak bu değişiklikler sizin için büyük bir fark yaratabilir. work_memEn azından ilk önce bu değişikliği deneyin .

İyi şanslar!

DÜZENLE:

Sıralamaya yardımcı olmak için ek bir dizin oluşturun

Dolayısıyla, zaman içinde ürün hattınız genişlerse, belirli sorgular birçok sonuç döndürebilir (binlerce, on binlerce?), Ancak yine de toplam ürün hattınızın yalnızca küçük bir alt kümesi olabilir. Bu durumlarda, bellekte yapılırsa sıralama oldukça pahalı olabilir, ancak sıralamaya yardımcı olmak için uygun şekilde tasarlanmış bir dizin kullanılabilir.

Dizinler ve ORDER BY açıklayan resmi PostgreSQL belgelerine bakın .

ORDER BYGerekliliklerinizle eşleşen bir dizin oluşturursanız

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

Postgres, dizini kullanmanın veya açık bir sıralama gerçekleştirmenin daha uygun maliyetli olup olmayacağına karar verir ve optimize eder. Postgres'in endeksi kullanacağının garantisi olmadığını unutmayın ; performansı optimize etmeye çalışır ve dizini kullanma veya açıkça sıralama arasında seçim yapar. Bu dizini oluşturursanız, oluşturulmasını haklı çıkarmak için yeterince kullanılıp kullanılmadığını görmek için dizini izleyin ve türlerinizin çoğu açık bir şekilde yapılıyorsa bırakın.

Yine de, bu noktada, 'para için en büyük patlama' ithalatınız muhtemelen daha fazla kullanacak work_mem, ancak dizinin sıralamayı destekleyebileceği durumlar var.


Ayrıca GIN önlemek için bağlantı tablosu kullanmayı düşünüyordum. Ancak bunun sıralamada nasıl yardımcı olacağını belirtmediniz. Bence işe yaramayacak. Sunduğunuz birleştirmeye oldukça benzediğini düşündüğüm ve bu işlemin puan ve başlıkta b-ağacı dizini kullanamadığını düşündüğüm, GIN sorgusu yoluyla toplanan bir dizi ürün kimliğiyle ürün tablosuna katılmaya çalıştım. Belki de yanlış indeks oluşturdum. Lütfen bunu biraz açıklar mısınız?
Yaroslav Stavnichiy

Özür dilerim, belki yeterince net bir açıklama yapmadım. work_memYapılandırmanızdaki değişiklik, 'diskte sıralama' sorununun yanı sıra yeniden kontrol koşulu sorununa bir çözüm olarak tasarlandı. Ürün sayısı arttıkça, sıralamak için ek bir dizine sahip olmanız gerekebilir. Lütfen açıklama için yukarıdaki düzenlemelerime bakın.
Chris
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.