LIMIT ile yavaş ORDER BY


11

Bu sorguyu var:

SELECT * 
FROM location 
WHERE to_tsvector('simple',unaccent2("city"))
   @@ to_tsquery('simple',unaccent2('wroclaw')) 
order by displaycount

Bundan memnunum:

"Sort  (cost=3842.56..3847.12 rows=1826 width=123) (actual time=1.915..2.084 rows=1307 loops=1)"
"  Sort Key: displaycount"
"  Sort Method: quicksort  Memory: 206kB"
"  ->  Bitmap Heap Scan on location  (cost=34.40..3743.64 rows=1826 width=123) (actual time=0.788..1.208 rows=1307 loops=1)"
"        Recheck Cond: (to_tsvector('simple'::regconfig, unaccent2((city)::text)) @@ '''wroclaw'''::tsquery)"
"        ->  Bitmap Index Scan on location_lower_idx  (cost=0.00..33.95 rows=1826 width=0) (actual time=0.760..0.760 rows=1307 loops=1)"
"              Index Cond: (to_tsvector('simple'::regconfig, unaccent2((city)::text)) @@ '''wroclaw'''::tsquery)"
"Total runtime: 2.412 ms"

Ancak LIMIT eklediğimde yürütme 2 saniyeden fazla sürüyor:

SELECT * 
FROM location 
WHERE to_tsvector('simple',unaccent2("city"))
   @@ to_tsquery('simple',unaccent2('wroclaw')) 
order by displaycount 
limit 20

Açıklamak:

"Limit  (cost=0.00..1167.59 rows=20 width=123) (actual time=2775.452..2775.643 rows=20 loops=1)"
"  ->  Index Scan using location_displaycount_index on location  (cost=0.00..106601.25 rows=1826 width=123) (actual time=2775.448..2775.637 rows=20 loops=1)"
"        Filter: (to_tsvector('simple'::regconfig, unaccent2((city)::text)) @@ '''wroclaw'''::tsquery)"
"Total runtime: 2775.693 ms"

Bence SİPARİŞ BY ve SINIR ile ilgili bir sorun olduğunu düşünüyorum. PostgreSQL'i dizini kullanmaya ve sonunda sipariş vermeye nasıl zorlayabilirim?

Alt sorgu yardımcı olmaz:

SELECT * 
FROM (
    SELECT * 
    FROM location 
    WHERE to_tsvector('simple',unaccent2("city"))
       @@ to_tsquery('simple',unaccent2('wroclaw')) 
    order by displaycount
) t 
LIMIT 20;

veya:

SELECT * 
FROM (
    SELECT * 
    FROM location 
    WHERE to_tsvector('simple',unaccent2("city"))
       @@ to_tsquery('simple',unaccent2('wroclaw'))
) t 
order by displaycount 
LIMIT 20;

Yanıtlar:


12

Benim tahminim bu sorgunuzu düzeltir:

SELECT * 
FROM   location 
WHERE     to_tsvector('simple',unaccent2(city))
       @@ to_tsquery('simple',unaccent2('wroclaw')) 
ORDER  BY to_tsvector('simple',unaccent2(city))
       @@ to_tsquery('simple',unaccent2('wroclaw')) DESC
         ,displaycount 
LIMIT  20;

Bu WHEREkoşulu ORDER BY, mantıksal olarak fazla olan, ancak location_displaycount_indexçok daha pahalı olduğu ortaya çıkıyor - sorgu planlayıcısı satırları dizine göre işlemek daha iyi olacağını varsayalım tutmak gerekir ilk öğe olarak tekrarlayın .

Temel sorun, sorgu planlayıcısının WHEREdurumunuzun seçiciliğini ve / veya maliyetini açıkça yanlış değerlendirmesidir . Sadece bunun neden olduğunu tahmin edebilirim.

Otovakumunuz var - ANALYZEmasalarınızda da çalışmalı mı? Dolayısıyla, tablo istatistikleriniz güncel mi? Çalıştırırsanız herhangi bir etki:

ANALYZE location;

Ve yeniden dene?

@@Operatörün seçiciliğinin yanlış değerlendirilmesi de olabilir. Mantıksal nedenlerle tahmin etmenin çok zor olduğunu düşünürdüm.


Sorgum sorunu çözmezse ve genellikle temel teoriyi doğrulamak için şu iki şeyden birini yapın:

İkincisi daha az müdahaleci ve sadece geçerli oturumu etkiler. Daha hızlı plan tarafından kullanılan yöntemleri bitmap heap scanve bitmap index scanaçık bırakır .
Ardından sorguyu yeniden çalıştırın.

BTW: Teori sağlamsa, sorgunuz (şimdi sahip olduğunuz gibi), FTS koşulunda daha az seçici bir arama terimiyle - beklediğinizin aksine - çok daha hızlı olacaktır. Dene.


1
Sorgu çalışır. Dizin taramasının kapatılması da işe yarar. ANALYZE çalışmıyor. Kapsamlı cevap için çok teşekkür ederim.
ziri

0

Bir LIMIT postgresql ayarı kullanırken, yalnızca satırın alt kümesini almak için en iyi olma planı. Ne yazık ki sizin durumunuzda bir şekilde yanlış bir seçim yapar. Bunun nedeni, tablo istatistiklerinin çok eski olması olabilir. VAKUM ANALİZİ konumu düzenleyerek istatistiği güncellemeyi deneyin;

Dizin kullanımını zorlamak normalde sıralı taramaların kullanımına izin verilmez (set enable_seqscan = false). Ancak sizin durumunuzda sıralı bir tarama yapmıyorsa, LIMIT ile sorgu için sadece farklı bir dizine geçer.

Analiz yardımcı olmazsa hangi postgresql sürümünü kullandığınızı söyleyebilir misiniz? Ayrıca tabloda kaç satır var?


Analiz yardımcı olmadı. Tabloda yaklaşık 36000 satır var ve ben postgresql 9.1 kullanıyorum.
ziri
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.