Elasticsearch ile pagination (sayfalama) yaparken şu hata ile karşılaşabilirsiniz:
The remote server returned an error: (400) Bad Request. Call: Status code 400 from: POST /courts/_search?typed_keys=true&request_cache=true. ServerError: Type: search_phase_execution_exception Reason: "all shards failed" CausedBy: "Type: illegal_argument_exception Reason: "Result window is too large, from + size must be less than or equal to: [10000] but was [20000]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting." CausedBy: "Type: illegal_argument_exception Reason: "Result window is too large, from + size must be less than or equal to: [10000] but was [20000]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting."
Bu hatanın sebebi aslında detayında da açıklandığı gibi, sonuçların getirilmesi kaynak tüketimi açısından sınırlandırılmış. Çözümü için index ayarlarınızdan “max_result_window” değerini arttırmanız gerekiyor. Console için örnek:
PUT ornek/_settings { "max_result_window" : 200000 }
Bu konulara burada değinmişler:
https://www.elastic.co/guide/en/elasticsearch/guide/current/pagination.html
https://www.elastic.co/guide/en/elasticsearch/guide/current/_fetch_phase.html
Açıklamaları bu şekilde:
“Belgelerinizin boyutuna, parça sayısına ve kullandığınız donanıma bağlı olarak, 10.000 ila 50.000 sonucu (1.000 ila 5.000 sayfa) derinlemesine sayfalamak mükemmel bir şekilde yapılabilir. Ancak yeterince büyük değerler söz konusu olduğunda, sıralama işlemi gerçekten çok ağır hale gelebilir ve büyük miktarda CPU, bellek ve bant genişliği kullanabilir. Bu nedenle, derin sayfalamaya karşı şiddetle tavsiyede bulunuyoruz”
Yani 10000’den fazla sonuç istiyorsanız, tüm veri bağlantılarında bellek kullanımı çok yüksek olacaktır çünkü her sorgu isteğinde daha fazla sonuç döndürmesi gerekir. Daha fazla veriniz ve daha fazla parçanız varsa, bu sonuçları birleştirmek verimsiz olacaktır. Ayrıca ES bunları önbelleğe alır, dolayısıyla yine daha fazla bellek kullanacaktır. Tam olarak ne kadar aldığınızı denemeniz ve hata yapmanız gerekir.
max_result_window dışında, pagination ve arama performansını etkileyen başka ayarlar da vardır. Bunları sıralayalım:
- index.max_inner_result_window: Nested sorgular için maksimum sonuç penceresi (default: 100).
- index.max_rescore_window: Rescoring yapılırken izin verilen maksimum sonuç sayısı (default: 10.000).
- index.max_terms_count: Terms query’de kullanılabilecek maksimum değer sayısı.
- index.max_docvalue_fields_search: docvalue_fields ile sorgulanabilecek maksimum alan sayısı.
- index.max_script_fields: Script field sayısı limiti.
Bu ayarlar genelde performans koruması amacıyla sınırlandırılmıştır.
Alternatif olarak, scroll veya searchAfter kullanmayı deneyebilirsiniz. Daha gerçek zamanlı sorgular için searchAfter daha uygundur.
Scroll API kullanımı
Scroll, büyük veri kümelerini parça parça çekmek için tasarlanmıştır. Özellikle batch işlem veya raporlama gibi senaryolarda idealdir.
POST /ornek/_search?scroll=1m
{
"size": 1000,
"query": {
"match_all": {}
}
}
Bu sorgu ilk 1000 sonucu getirir ve bir scroll_id döner. Devamındaki sonuçları almak için:
POST /_search/scroll
{
"scroll": "1m",
"scroll_id": "DXF1ZXJ5QW5..."
}
Search After kullanımı
search_after, daha çok gerçek zamanlı sayfalama için uygundur. from/size yaklaşımından farklı olarak, bir önceki sonucun sıralama değerini alır ve oradan devam eder.
POST /ornek/_search
{
"size": 10,
"query": {
"match_all": {}
},
"sort": [
{ "created_at": "asc" },
{ "_id": "asc" }
]
}
İlk sayfa sonuçları geldikten sonra, son kaydın sort alanlarını kullanarak devam edersiniz:
POST /ornek/_search
{
"size": 10,
"query": {
"match_all": {}
},
"search_after": ["2023-09-01T10:00:00", "id123"],
"sort": [
{ "created_at": "asc" },
{ "_id": "asc" }
]
}
Bu yöntemle sonsuz kaydırma (infinite scroll) tarzı gerçek zamanlı listeler yapılabilir.
Scroll için döküman: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-scroll.html
SearchAfter dökümanı: https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-search-after.html
Yakında bunların C# ile kullanımına değineceğim.
Yorum bırakın