Nasıl farklı hızlandırmak için?


16

Bazı zaman serisi verileri basit bir seçim farklı var:

SELECT DISTINCT user_id
FROM events
WHERE project_id = 6
AND time > '2015-01-11 8:00:00'
AND time < '2015-02-10 8:00:00';

Ve 112 saniye sürüyor. İşte sorgu planı:

http://explain.depesz.com/s/NTyA

Uygulamam birçok farklı işlemi önceden yapmak zorunda ve bunun gibi sayıyor. Bu tür verileri almanın daha hızlı bir yolu var mı?

Yanıtlar:


19

Muhtemelen bunu duymak istemiyorum, ama hızlandırmak için en iyi seçenek SELECT DISTINCTolduğunu kaçınmak DISTINCT ile başlayacak. Birçok durumda (hepsi değil!) Daha iyi veritabanı tasarımı veya daha iyi sorgularla önlenebilir.

Bazen, GROUP BYdaha hızlıdır, çünkü farklı bir kod yolu gerektirir.

In sizin özel durumda size kurtulabilirsiniz gibi görünmüyor DISTINCT. Ancak, bu tür birçok sorgunuz varsa, sorguyu özel bir dizinle destekleyebilirsiniz:

CREATE INDEX foo ON events (project_id, "time", user_id);

Ekleme user_id, yalnızca bundan sadece dizin taramaları alırsanız yararlıdır . Ayrıntılar için bağlantıyı takip edin. Sorgu zamanınızın% 90'ını tüketen pahalı Bitmap Öbek Taramasını sorgu planınızdan kaldıracaktır .

Sizin EXPLAINçıkış sorgusu yarım milyon eşleşen satırların 2491 farklı kullanıcıları dışarıda yoğunlaşmaya olmayacağını söylüyor. Ne yaparsanız yapın, bu süper hızlı olmayacak, ancak önemli ölçüde daha hızlı olabilir.

Sorgularınızdaki zaman aralıkları her zaman aynıysa, MATERIALIIZED VIEWkatlama user_idbaşına (project_id, <fixed time intervall>)uzun bir yol kat eder. Ancak değişen zaman aralıklarında şansınız yok. Belki de kullanıcıları saatte veya başka bir minimum zaman biriminde en az katlayabilirsiniz ve bu, önemli ek yükü garanti etmek için yeterli performans satın alır.

Nitpick:
Büyük olasılıkla, tahminler "time"gerçekten şöyle olmalı:

AND "time" >= '2015-01-11 8:00:00'
AND "time" <  '2015-02-10 8:00:00';

Kenara: Tanımlayıcı olarak
kullanmayın time. Bu bir var amaçlı sözcüğünü standart SQL ve Postgres bir temel türüdür.


Sadece indeks taramaları hakkında biraz okudum, denemek istiyorum.
Sam

Ne yazık ki, zaman aralığı sabit değildir.
Sam

@Sam: Örnek sorgunuz önerilen dizine ne kadar hızlı ulaştı?
Erwin Brandstetter

3
@edwin: Henüz üretimi denemedim. Ancak, orijinal (aynı verilerle) orijinal sorgu çalıştırdı ve 3678.780 ms sürdü. Sonra indeksi ekledim ve 170.156 ms'ye kadar hızlandırdı. Plan şimdi 'Etkinliklerde foo kullanarak yalnızca Dizin Tarama' içeriyor.
Sam

1
@Sam: Güzel! Ben de bunu hedefliyordum.
Erwin Brandstetter

2

Sam'in davası ve Erwin'in cevabı hakkındaki testim

drop table t1
create table t1 (id int, user_id int, project_id int, date_time timestamp without time zone) ;

insert into t1 -- 10 million row - size="498 MB"
select row_number() over(), round(row_number() over()/1000), round(row_number() over()/100000) , date
from generate_series('2015-01-01'::date, '2016-12-01'::date,'6 seconds'::interval
) date 
limit 10000000

-- before indexing - 10000000 row - output=100 row - time=2900ms
SELECT DISTINCT user_id
FROM t1
WHERE project_id = 1
AND date_time > '2015-01-01 8:00:00'
AND date_time < '2016-12-01 8:00:00' ;

CREATE INDEX foo ON t1 (project_id, date_time, user_id); -- time process=51.2 secs -- size="387 MB"         

-- after indexing - 10000000 row - output=100 row - time= 75ms (reduce ~ 38 times)
SELECT DISTINCT user_id
FROM t1
WHERE project_id = 1
AND date_time > '2015-01-01 00:00:00'
AND date_time < '2016-12-01 00:00:00' ;

Erwin, "Muhtemelen bunu duymak istemezsiniz, ancak SELECT DISTINCT'i hızlandırmak için en iyi seçenek, DISTINCT'in başlamasını önlemektir. Birçok durumda (hepsi değil!) Daha iyi veritabanı tasarımı veya daha iyi sorgularla önlenebilir ". Bence haklı, "farklı, gruplama, sıralama" (varsa) kullanmaktan kaçınmalıyız.

Sam'in davası gibi bir durumla karşılaştım ve Sam'in olay tablosundaki bölümleri aya göre kullanabileceğini düşünüyorum. Sorguladığınızda veri boyutunuzu küçültür, ancak yukarıdaki sorgu yerine yürütmek için bir işleve (pl / pgsql) ihtiyacınız vardır. İşlev, sorguyu yürütmek için uygun bölümleri (koşullara bağlı olarak) bulur.


2
> Bence haklı, "farklı, gruplama, sıralama ölçütü" kullanmaktan kaçınmalıyız - ve ayrıca SELECT, INSERT ve UPDATE. Bu yapılardan kaçınırsak, veritabanımız çok hızlı olacaktır!
greatvovan
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.