Bu veritabanına (RT ( Request Tracker ) biletlerini saklamak) yönelik tam metin sorgularının yürütülmesi çok uzun zaman alıyor gibi görünüyor. Ekler tablosu (tam metin verilerini içeren) yaklaşık 15 GB'dir.
Veritabanı şeması aşağıdaki gibidir, yaklaşık 2 milyon satır:
rt4 = # \ d + ekler
"Public.attachments" tablosu
Sütun | Türü | Değiştiriciler | Depolama | Açıklama
----------------- + ----------------------------- + - -------------------------------------------------- ------ + ---------- + -------------
id | tam sayı | null değil varsayılan nextval ('attachments_id_seq' :: regclass) | düz |
işlem kimliği | tam sayı | boş değil | düz |
ebeveyn | tam sayı | boş değil varsayılan 0 | düz |
mesaj kimliği | karakter değiştirme (160) | | genişletilmiş |
konu | karakter değiştirme (255) | | genişletilmiş |
dosyaadı | karakter değiştirme (255) | | genişletilmiş |
içerik türü | karakter değiştirme (80) | | genişletilmiş |
içerik kodlama | karakter değiştirme (80) | | genişletilmiş |
içerik | metin | | genişletilmiş |
başlıklar | metin | | genişletilmiş |
yaratıcısı | tam sayı | boş değil varsayılan 0 | düz |
oluşturuldu | saat dilimi olmadan zaman damgası | | düz |
içerik dizini | tsvector | | genişletilmiş |
Endeksler:
"attachments_pkey" BİRİNCİL ANAHTAR, btree (id)
"attachments1" btree (üst öğe)
"attachments2" btree (işlem kimliği)
"attachments3" btree (üst öğe, işlem kimliği)
"contentindex_idx" cin (contentindex)
OID var: hayır
Ben çok hızlı bir şekilde kendi veritabanı (<1s) gibi bir sorgu ile sorgulayabilirsiniz:
select objectid
from attachments
join transactions on attachments.transactionid = transactions.id
where contentindex @@ to_tsquery('frobnicate');
Ancak, RT aynı tabloda tam metin dizin araması gerçekleştirmesi gereken bir sorgu çalıştırdığında, tamamlanması genellikle yüzlerce saniye sürer. Sorgu analizi çıktısı aşağıdaki gibidir:
Sorgu
SELECT COUNT(DISTINCT main.id)
FROM Tickets main
JOIN Transactions Transactions_1 ON ( Transactions_1.ObjectType = 'RT::Ticket' )
AND ( Transactions_1.ObjectId = main.id )
JOIN Attachments Attachments_2 ON ( Attachments_2.TransactionId = Transactions_1.id )
WHERE (main.Status != 'deleted')
AND ( ( ( Attachments_2.ContentIndex @@ plainto_tsquery('frobnicate') ) ) )
AND (main.Type = 'ticket')
AND (main.EffectiveId = main.id);
EXPLAIN ANALYZE çıktı
QUERY PLAN
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------
Toplam (maliyet = 51210.60..51210.61 satır = 1 genişlik = 4) (gerçek zaman = 477778.806..477778.806 satır = 1 döngü = 1)
-> İç İçe Döngü (maliyet = 0.00..51210.57 satır = 15 genişlik = 4) (gerçek zaman = 17943.986..477775.174 satır = 4197 döngü = 1)
-> İç İçe Döngü (maliyet = 0.00..40643.08 satır = 6507 genişlik = 8) (gerçek zaman = 8.526..20610.380 satır = 1714818 döngü = 1)
-> Seq Scan biletlerinde ana (maliyet = 0.00..9818.37 satır = 598 genişlik = 8) (gerçek zaman = 0.008..256.042 satır = 96990 döngü = 1)
Filtre: (((durum) :: metin 'silindi' :: metin) AND (id = etkiliid) AND ((tür) :: metin = 'bilet' :: metin))
-> İşlemler işlemlerinde işlem1'i kullanarak Dizin Taraması_1 (maliyet = 0.00..51.36 satır = 15 genişlik = 8) (gerçek zaman = 0.102..0.202 satır = 18 döngü = 96990)
Endeks Koşulu: (((nesne türü) :: text = 'RT :: Bilet' :: metin) AND (objectid = main.id))
-> Ekler_2 (maliyet = 0.00..1.61 satır = 1 genişlik = 4) eklerde2 ekleri kullanarak Dizin Taraması (gerçek zaman = 0.266..0.266 satır = 0 döngü = 1714818)
Endeks Koşulu: (transactionid = transaction_1.id)
Filtre: (contentindex @@ plainto_tsquery ('frobnicate' :: metin))
Toplam çalışma süresi: 477778.883 ms
Anlayabildiğim kadarıyla, sorun, contentindexalanda oluşturulan dizini kullanmıyor ( contentindex_idx), bunun yerine ekler tablosundaki çok sayıda eşleşen satırda bir filtre yapıyor olması gibi görünüyor. Açıklama çıktısındaki satır sayıları da yakın ANALYZEzamandan sonra bile çok yanlış görünüyor : tahmini satırlar = 6507 gerçek satırlar = 1714818.
Bundan sonra nereye gideceğimi pek bilmiyorum.