Elasicsearch Kullanım Tecrübemiz #2

Neslihan Esra Altınışık
Apinizer
Published in
8 min readNov 11, 2020

Yazı serisinin ilkinde Aşama1 kısımda Elasticsearch’i neden seçtiğimizi, Aşama2'de Elasticsearch ile literatür taraması sonucu uyguladığımız ayarlardan bahsettim. Bu yazıda, indeks temasının performansa etkisi üzerinde kafamızda soru işareti bırakan konuları değerlendirmek için testler yaptık.

Seri İçeriği⚪️ Elasticsearch Kullanım Tecrübemiz #1
Aşama 1: Couchbase & InfluxDb & Elasticsearch hangisi bizim için doğru karar?
Aşama 2: Bizim için doğru Elasticsearch ayarı nedir?
🔵️ Elasticsearch Kullanım Tecrübemiz #2
Aşama 3: Performans Testleri
⚪️ Elasticsearch Kullanım Tecrübemiz #3
Aşama 4: Shard ve Disk Boyutu
Aşama 5: Önemli Kontroller

Aşama 3: Performans Testleri

Performansa etkisinin ne olacağını ve ne kadar olacağını ölçmek için bazı durumların test edilmesine karar verdik. Çünkü araştırmalar ve öneriler doküman yapısının en ucuz (cheap) olacak şekilde modellemesi ve olabildiğince az field üzerinde arama yapılması noktası üzerinde durmaktaydı. Test edilecek durumları (meraklarımızı) şu şekilde kısalttık;

Durum 1: _source ve index mapping parametrelerinin disk alanına ve sorgu hızına etkisi ne olur? Varsayılan mapping’deki index ile bu parametrelere sahip index arasındaki fark nedir?

Durum 2: Durum1 üzerindeki sonuçların 10M doküman üzerindeki değişimini ve varsayılan ayarlar ile indexleme yapıldığında ölçülen değerlerin farkları neler?

Durum 3: Custom template’e sahip indeks ile varsayılan ayarlar ile oluşturulan indeks arasında farkı var mı?

Durum 4: Yüklü veri üzerinde Elasticsearch performansı gerçekten iyi mi?

📓 Not: Bu durumları ele alırken farklı kriterler ölçmek amaçlandığı ve farklı doküman yapıları kullanıldığı için kıyaslanmamalıdır.

Durum 1: index mapping parametresinin true ve false olduğu indexler üzerinde index boyutu ve disk boyutu kıyaslaması yapılacaktır.

Bu durumu test etmek için durum1kosul1 ve durum1kosul2 olarak iki farklı mapping’e sahip index oluşturuldu. Bu indexlerin mapping'i şöyledir;

durum1kosul1 Index’ine ait Mapping
durum1kosul2 Index’ine ait Mapping

durum1kosul1 ve durum1kosul2 index'leri için örnek bir doküman;

# message1 ve message2 alanlarındaki metin 500 karakterden oluşmaktadır.
{
"message1":"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or.",
"message2":"But I must explain to you how all this mistaken idea of denouncing pleasure and praising pain was born and I will give you a complete account of the system, and expound the actual teachings of the great explorer of the truth, the master-builder of human happiness. No one rejects, dislikes, or avoids pleasure itself, because it is pleasure, but because those who do not know how to pursue pleasure rationally encounter consequences that are extremely painful. Nor again is there anyone who loves or.",
"age":20
}

Bu indexler üzerinde aşağıdaki sorgular çalıştırıldı.

* Sorgudaki size parametresinin değeri 0 ve 20 değerleri verilerek ayrı sorgulanmıştır.

500 bin doküman üzerinde çalıştırılan sorgu sonuçları ve index boyutu;

Sonuç olarak;

  • source özelliği, dokümanın ya da alanların saklanıp saklanılmayacağını kontrol eder. excludes ve includes parametresi ile hangi alanların source’da olup olmayacağı kontrol edilebilir. Disk alanını düşürdüğü için bu özellik kullanılsa da _source:false olarak ayarlandığında index içerinde yer alan source kısmına veri kaydedilmeyeceği için SearchHit’te sonucun bulunacağı fakat verinin gelmeyeceğine dikkat edilmelidir. Yalnızca sorgularda fetch edilmeyecek alanlara uygulanabilir.
  • index özelliği, alanın indexlenip indexlenmediğini kontrol eder. source: true iken alan index:false ayarlanmış ise arama yapıldığında (bu alan üzerinden arama yapılamaz, burada kastedilen başka bir alan üzerinden arama yapılmasıdır) dönen SearchHit nesnesinde bu alanın gelmeyeceğine dikkat edilmelidir.
  • Indexlerin disk üzerindeki boyutu ele alındığında durum1kosul1, durum1kosul2’ye göre daha küçük boyuta sahiptir. Bu iki index arasındaki 2mb’lık fark ise age alanındaki index parametresinden kaynaklanmaktadır.
  • Numerik alanlarda sorgu yapılmayacaksa index:false ve _source exclude olması yer kaplamaması açısından değerlendirilebilir. Çünkü aggregation yapılırken performans olarak bir fark görülmemiştir.
  • durum1kosul1 ve durum1kosul2 arasında size:0 iken age alanı üzerinden yapılan aggregation’ın daha hızlı olduğu görülmektedir. Yani indexli alan üzerindeki aggregation daha hızlı çalışmıştır. Fakat uygulamamızda çoğu zaman sorgular cache üzerinden çalışacağından ve cache’siz sorgular arasındaki fark çok büyük olmadığından bu alanın indexli olması durumu ignore edilebilir. (Kaynaklarımız sınırlı olsa da bizim için bu alanların disk boyutu o kadar da büyük yer kaplamadığından -bu örnekte 500K için 2mb- biz index ile devam etmeye karar verdik)
  • size:20 olduğunda sonuçların cachelenmediği dikkat çekmiştir. Bunun da her sorgu cevaplandığında, dönen SearchHit nesnesinin “get + fetch” edilmesinin farklılık gösterebileceğinden olduğuna kanaat getirilmiştir. Böylece sorgu birden fazla çağrıldığında cevaplanma süresi azalmamaktadır. Bu yüzden aggregation sorgularında size:0 değeri ile kullanımın tercih edilmesi gerekliliği gözükmektedir. Zaten aggregation için SearchHit’ten ziyade Bucket değerleri önemlidir.
  • Bir alana sadece aggregation sorgusu yapılacaksa index:false olabilir. Çünkü disk boyutunun azaltığı görülmüştür. Fakat bizim platformumuzda varsayılan değeri olan index:true kullanımı tercih edilmesine karar verilmiştir.
  • text veri tipine sahip alanda aggregation sorgusu çalıştırmak için fielddata:true olmalıdır.

Durum 2: Bu bölümde, Durum1'de doküman sayısı arttığında durum1kosul1 ve durum1kosul2 indexleri ile varsayılan mapping’e sahip indeksin disk boyutu ve arama performansları arasındaki fark nedir? sorusuna cevap bulmak ve diğer en çok kullanılan Term ve Match sorgularının performansı ölçmek için 10M’luk dokümanlara sahip indexler üzerinden tekrar test yapılmıştır.

  • Yukarıdaki bölümde durum1kosul1 ifadesi ile belirtilen mapping durum2kosul1 indexine uygulanmıştır.
  • Yukarıdaki bölümde durum1kosul2 ifadesi ile belirtilen mapping durum2kosul2 indexine uygulanmıştır.
  • durum2kosul3 index’inde ise her hangi bir mapping işlemi uygulanmamıştır. Varsayılan mapping özellikleri ile indexlenmiştir.

durum2kosul1, durum2kosul2 ve durum2kosul3 indexleri üzerinde aşağıdaki sorgular çalıştırıldı.

* Sorgudaki size parametresinin değeri 0 ve 20 değerleri verilerek ayrı sorgulanmıştır.

10 milyon doküman üzerinde çalıştırılan sorgu sonuçları ve index boyutu;

* Term query, index değeri false olduğundan age üzerinde sorgu çalıştırılamadı.

Sonuç olarak;

  • index:false ayarının olduğu index’in, disk boyutuna göre diğer indexlerle büyük bir fark yaratmamıştır.
  • Durum 1'deki sonuca paralel olarak 10M’lik sonuca göre index:false olmasının aggregation işlemlerinde gözle görünür bir farkı bulunmamaktadır. Az da olsa indexlenen alan üzerinde sorgu daha hızlı çalışmıştır.
  • (Doğal olarak) aggregation yapılacak küme boyutu arttıkça performansın düştüğü gözükmektedir. Sayılara bakıldığında aggregation için 1sn sınırına yaklaşıldığından 10M’den büyük bir veri seti kullanmamızın doğru olmadığı sonucuna varılmıştır. Bu da uygulamamızdaki filtreleri buna göre tahminsel bir şekilde güncellememiz ve kural koyma gereksinimi doğurmuştur.
  • index:false olan alan üzerinde sorgulama yapılmasına Elasticsearh’in izin vermeyeceği dikkat edilmelidir.
  • Text tipinde ve exclude edilmiş message2 alanı, index:true iken full-text aramaya izin verse de exclude olduğundan SearchHit’de bu alana ait değeri getirmemiştir. Bizim sorgularımızda tüm alanların getirilmesi gerektiği için herhangi bir alan exclude olmaması gerektiğine karar verilmiştir.

Durum 3: Custom template’e sahip index ile varsayılan ayarlar ile oluşturulan index karşılaştırılması

Buraya kadar yapılan tüm işlemler, disk boyutunu optimize etme ve daha performanslı sorgu çalıştırmak için hangi ayarları yapacağımıza dair araştırma ve testlerden oluşmaktadır. Bu durum altında da oluşturduğumuz mapping’a sahip durum3kosul1 indexi ile varsayılan ayarlardaki durum3kosul2 indexi arasında kıyaslama yaparak ne kazandığımızı ya da kaybettiğimizi ölçmeye çalıştık. Bu indexler 1 milyon dokümana sahiptir.

Bu durumu test etmek için durum3kosul1 ait mapping’in ve ayarların yer aldığı durum3kosul1template adlı template oluşturuldu. durum3kosul2 indexi için varsayılan ayarlarda indexleme yapılacağı için herhangi bir template’e gerek yoktur. Elasticsearch varsayılan mapping değerleri ve ayarlar ile indexleme yapar. Bu indexler;

durum3kosul1 Index’ine ait Mapping
durum3kosul2 Index’ine ait Mapping

Bu indexler üzerinde gerçek kullanıma uygun daha karışık aggregation ve full-text sorgusu üzerinden test edildi. durum3kosul2 indexi üzerinde yapılan sorgularda kısaltılmamış alan adları kullanılmıştır. Bu sorgular;

Complex Query
Complex Full-Text Query

1 milyon doküman üzerinde çalıştırılan sorgu sonuçları ve index boyutu;

Sonuç olarak;

  • durum3kosul1 indexinde full-text yapılacak alanlara text tipi, aggregation ve query çalıştırılacak alanlara keyword tipi ve sayısal alanların boyutu baz alınarak veri tipi ataması yapılmıştır. Bu konfigürasyon ayarı 600 mb’lık veri farkını doğurmuştur. Doküman sayısının 100 milyonlara ulaşması durumunda ciddi fark oluşacağı gözükmektedir.
  • Sorgular ilk çalıştırıldığında durum3kosul1 index’i üzerinde daha hızlı çalışsa da cachelenen sorguların çalışma süreleri, 2 index’inde birbirine yakındır.
  • Ek bilgi olarak, keyword veri tipine ait ignore_above parametresi ile yazılan değerin üstündeki karakterler sadece saklanır, ama bu saklanan alanlarda arama yapılmamaktadır.

Durum 1,2,3 Sonucu olarak;

Yaptığımız çalışmalar işe yaramış gözüküyor. 😸 Platformumuzdaki elasticsearch cluster’ı hem time-series-database hem de full-text-search database olarak çalışır durumdadır.

  • Mapping’lerin düzgün yapılması ile disk boyutu ciddi anlamda küçültü. Tüm alanlarımız indexli ve source’da var. Fakat gereksiz büyük tip (text yerine keyword kullanımı tercih edilen alanlar oldu, sayısal değerler için de byte ve integer kullandığımız yerler oldu) kullanımları temizlendi.
  • Index sayısı, shard sayısı, replika sayıları düzenlendi.
  • Sorgular birden çok indexte, indexleme ise en son indexte gerçekleşiyor. En sonuncu index dışındakiler tüm indexler read-only durumda. Böylece index lifecycle yönetimi kolaylaştı.
  • Index lifecycle yönetiminin ölçemediğimiz (en azından tutarlılık olarak ) olumlu etkileri olduğunu düşünüyoruz (umut ediyoruz 😺).
  • Uygulama içi cachelenemeyen sorgular var mı kontrolü yaptık ve olmayanları düzelttik. Zaman kullanan sorgularımızda eskiden anlık zamanın alınmasına dayalı sorgularımız, cache’lenebilmesi için dakikaya round edilmesi sağlandı. Aggregationlarımız sonuç getirmeyecek şekilde ayarlandı. (size:0)
  • Cache kullanımı ile sonuçlar hissedilir şekilde hızlı gelmeye başladı.
  • Term, match query kullanılan alanlar üzerinden geçildi.
  • Default sorgu sonuçlarını kullanmak yerine includes anahtar kelimesi ile sadece ihtiyaç duyulan alanların getirilmesi ile sorgu performansı artırıldı.

Durum 4: Yüklü veri üzerinde Elasticsearch performansı gerçekten iyi mi?

550M dokümana sahip index üzerinden sorgu hızlarını test ettik.

Bu durumu test etmek için durum4kosul1 indexine mapping’e sahip index oluşturuldu. Bu index’a ait mapping ve örnek bir dokümanı şöyledir;

durum4kosul1 Indeksine ait mapping
durum4kosul1 indeksinin örnek bir dokümanı

durum4kosul1 index’i üzerinde aşağıdaki sorgular çalıştırılmıştır;

* Bu sorgudaki field name ve value özelliğine atanan değer, veri tipine göre farklılık göstermektedir.

550 milyon doküman olan ve boyutu 96.3gb sahip durum4kosul1 index’i üzerinde çalıştırılan sorguların sonuçları;

Sonuç olarak;

  • Metin1 alanında 3 kelimelik bir text, Metin2 alanında 15 kelimelik bir text tutulmaktadır. Bu alanlar üzerindeki match sorguları kıyaslandığında indeksli veri büyüdükçe sorgu yavaşlıyor.
  • Number1 alanı 0–10 aralığında, Number2 alanı 0–100 aralığında, Number3 alanı 0–1000 aralığında, Number4 alanı 0–10000 aralığında değer almaktadır. Sayısal alanlarda değerlerin farklılık ve çeşitlilik (cardinality) sayısının artmasıyla hem term sorgusu hem match sorgusunun cevaplanma süresinin azaldığı tespit edilmiştir. Bu yüzden match yerine term ile arama yapılabilir.
  • Genel olarak match ve term sorgusu kıyaslığında, term sorgusunun her türlü daha hızlı çalışmıştır.
  • Aggregation sorgusu çalıştırıldığında yaklaşık 28 saniyede sonuçlanmıştır, birden fazla çalıştırılmak istendiğinde de 504 (Gateway Time-out) hatası alındı. Dolayısıyla büyük veri kümeleri üzerinde aggregation yapılması anlamlı gözükmemektedir.

👈 Bir önceki yazıda, zaman bazlı veri tabanı olarak neden Elasticsearch’i seçtik ve doğru ayarlar ne olmalı sorusuna cevap aramaya çalıştık.

👉 Bir sonraki yazıda, dikkat edilmesi gereken kontrollere ve shard ve disk boyutuna değindik.

--

--