PostgreSQL neden dizine alınmış sütunda sıralı tarama yapar?


163

Çok basit bir örnek - bir tablo, bir dizin, bir sorgu:

CREATE TABLE book
(
  id bigserial NOT NULL,
  "year" integer,
  -- other columns...
);

CREATE INDEX book_year_idx ON book (year)

EXPLAIN
 SELECT *
   FROM book b
  WHERE b.year > 2009

bana verir:

Seq Scan on book b  (cost=0.00..25663.80 rows=105425 width=622)
  Filter: (year > 2009)

Bunun yerine neden dizin taraması YAPMAZ? Neyi kaçırıyorum?

Yanıtlar:


237

SELECT, tablodaki tüm satırların yaklaşık% 5-10'undan fazlasını döndürürse, sıralı tarama, dizin taramasından çok daha hızlıdır.

Bunun nedeni, bir dizin taramasının her satır için birkaç GÇ işlemi gerektirmesidir (dizindeki satıra bakın, ardından yığından satırı alın). Sıralı bir tarama, her satır için yalnızca tek bir GÇ gerektirirken - veya diskteki bir blok (sayfa) birden fazla satır içerdiğinden daha az, böylece tek bir GÇ işlemiyle birden fazla satır getirilebilir.

Btw: Bu, diğer DBMS için de geçerlidir - "yalnızca dizin taramaları" gibi bazı optimizasyonlar bir kenara alınır (ancak bir SELECT * için böyle bir DBMS'nin "yalnızca dizin taraması" için gitmesi pek olası değildir)


7
@Frank: Bu yüzden "yaklaşık olarak" dedim :) Ama bunu gösterdiğin için teşekkürler
a_horse_with_no_name

İlginç, bu benim için pek çok şeyi açıklıyor :) Gerçekten de yıl> 2010'a göre seçim yaptığımda indeks taraması yapıyor. Teşekkür ederim!
Alex Vayda

5
Ayrıca, sıralı bir tarama aynı anda yığından birkaç sayfa isteyebilir ve çekirdekten bir sonraki öbeği getirmesini isteyebilir ve mevcut tek bir dizin taraması aynı anda bir sayfa alır. (Bir bitmap taraması ikisi arasında bir uzlaşma sağlar, genellikle bir dizin taraması için yeterince seçici olmayan, ancak yine de tam bir tablo taramasını hak edecek kadar seçici olmayan sorgular için bir planda göründüğünü görürsünüz)
araqnid

4
İlginç soru, veritabanının, sorgunun önce yapmadan kaç satır döneceğini nasıl bildiğidir? Farklı değerlerin sayısı ve masa boyutu gibi istatistikleri bir yerde saklıyor mu?
Laurent Grégoire

7
@ LaurentGrégoire: evet, veritabanı satır sayısı ve değerlerin dağılımı hakkındaki istatistikleri depolar. Ayrıntılar için kılavuza bakın: postgresql.org/docs/current/static/planner-stats.html
a_horse_with_no_name

13

Eğer mı ANALİZ tablo / veritabanı? Peki ya istatistikler ? Yılın> 2009 olduğu birçok kayıt olduğunda, sıralı bir tarama, dizin taramasından daha hızlı olabilir.


0

İndeks taramasında, bir satırdan diğerine bir sonraki fiziksel bloğu okumaktan (sıralı taramada) 1000 kat daha yavaş olan kafa atlamalarını okuyun.

Dolayısıyla, (alınacak kayıt sayısı * 1000) toplam kayıt sayısından azsa, indeks taraması daha iyi sonuç verecektir.


0

@a_horse_with_no_name bunu oldukça iyi açıkladı. Ayrıca, gerçekten bir dizin taraması kullanmak istiyorsanız, genellikle where cümlesinde sınırlı aralıklar kullanmalısınız. örneğin - yıl> 2019 ve yıl <2020.

Çoğu zaman istatistikleri bir tabloda güncellenmez ve kısıtlamalar nedeniyle bunu yapmak mümkün olmayabilir. Bu durumda, optimizer> 2019 yılında kaç satır alması gerektiğini bilemez. Böylece tam bilgi yerine sıralı bir tarama seçer. Sınırlı bölümler çoğu zaman sorunu çözecektir.

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.