DuckDB'de Parquet Sayfalama: file_row_number mi, OFFSET mi?
DuckDB'de Parquet sayfalamada file_row_number ile OFFSET karşılaştırması: performans farkı ve gizli veri bütünlüğü riski.
Yirmi milyon satırlık bir Parquet dosyasını sayfa sayfa döndüren stateless bir servis için DuckDB'de iki yaklaşım karşılaştırıldı: klasik LIMIT/OFFSET ve read_parquet'in file_row_number seçeneğiyle satır aralığı filtreleme. 163 row group içeren dosyada satır aralığı yaklaşımı OFFSET'e göre 2.53 kat daha hızlı çıktı ve bu sonuç 37 denemenin tamamında tekrarlandı; ancak kazanç tamamen dosyanın kaç row group'a bölündüğüne bağlı, tek row group'luk dosyalarda neredeyse kayboluyor.
Beklenmedik bulgu ise DuckDB'nin OFFSET sorgularını arka planda file_row_number tabanlı bir hash join'e dönüştürüp benzer row group atlamasını zaten yaptığı; bu yüzden OFFSET kuadratik değil. Ancak bu rewrite yalnızca LIMIT değeri 1.000.000 satırın altındayken (LIMIT_MAX_VAL ve late_materialization_max_rows ayarlarına bağlı bir eşik) tetikleniyor; eşik aşılınca veya WHERE eklenince fark 5-6 kata çıkıyor.
Asıl kritik nokta performans değil doğruluk: LIMIT/OFFSET'in ORDER BY olmadan hiçbir sıralama garantisi yok. preserve_insertion_order kapatılıp çoklu thread ile sayfalama yapıldığında toplam satır sayısı tam 20 milyon çıkmasına rağmen verinin yaklaşık %30'u ya kayboluyor ya da tekrar ediyor ve hata fırlamıyor. Bu da satır sayısı doğrulamasının export bütünlüğü için yetersiz olduğunu, hash tabanlı doğrulamanın gerekli olduğunu gösteriyor.