# Analitik Veri Tabanı Sistemleri: OLAP ve ClickHouse

> OLAP kuramı, sütun yönelimli depolama, ClickHouse MergeTree, sorgu yürütme, SQL optimizasyonu, dağıtık sistemler, Oracle CDC, analitik güvenliği ve deneysel performans mühendisliği.

- Author: Muhammet Ali Köker
- Language: tr
- Canonical: https://alikoker.com.tr/analitik-veri-tabani-sistemleri-olap-clickhouse
- Translation: https://alikoker.com.tr/en/analytical-database-systems-olap-clickhouse
- Published: 2026-10-27T21:16:00+03:00
- Usage: https://alikoker.com.tr/telif-hakki-ve-kullanim-kosullari
- Modified: 2026-10-27T23:34:16+03:00
- Type: article

Çevrimiçi işlem işleme (OLTP), kısa işlemlerle az sayıda kaydın tutarlı okunmasını ve değiştirilmesini; çevrimiçi analitik işleme (OLAP) ise büyük veri kümelerinin taranmasını, filtrelenmesini, gruplanmasını ve istatistiksel çözümlemesini hedefler. OLTP iş yüklerinde düşük işlem gecikmesi ve eşzamanlı yazma belirleyiciyken OLAP iş yüklerinde okunan sütun miktarı, sıkıştırma, paralel yürütme ve agregasyon maliyeti öne çıkar. Oracle, PostgreSQL ve MySQL gibi genel amaçlı [veri tabanı yönetim sistemleri](/veri-tabani-yonetim-sistemleri) analitik sorguları da çalıştırabilir; ancak işlemsel verinin bu sistemlerde, analitik kopyasının ise ClickHouse üzerinde tutulması, iş yüklerinin ayrı ayrı optimize edilmesine olanak tanır.

ClickHouse, sütun yönelimli depolama ve MergeTree ailesi üzerinden yüksek hacimli analitik sorgulamalar için geliştirilmiş bir veritabanı yönetim sistemidir. Sıralama anahtarları, seyrek birincil indeks, granül temelli veri erişimi, veri parçası birleştirmeleri, materyalleştirilmiş görünümler ve dağıtık sorgu yürütme birlikte ele alındığında sorgu davranışı açıklanabilir. Bu özelliklerin hiçbiri her iş yükü için mutlak hız veya kaynak kazanımı garantisi vermez.

## Ünite 1: OLTP, OLAP ve HTAP Sistemlerinin Temelleri

İşlemsel ve analitik sistemler yalnız farklı ürünler değil, farklı erişim örüntüleridir. Noktasal satır erişimi ile geniş sütun taraması arasındaki fark, depolama düzeninin neden değiştiğini açıklar.

![OLTP ve OLAP erişim örüntüsü animasyonu](https://alikoker.com.tr/svg/oltp-olap-access-pattern.svg "OLTP ve OLAP erişim örüntüleri")


OLTP işlemleri çoğunlukla belirli bir anahtarla az sayıda satıra erişir, kısa işlem sınırları içinde kalıcı ve tutarlı değişiklikler yapar. OLAP ise geniş satır kümeleri üzerinde projeksiyon, filtreleme, birleştirme ve agregasyon yürütür. Satır yönelimli depolama ile B+ ağaç erişiminin OLTP için uygun olması, aynı fiziksel düzenin analitik taramalarda verimli olacağını göstermez. ClickHouse'un önceliği büyük veri kümelerinin seçilen sütunlarını hızlı okumak, CPU çekirdekleri arasında paralel işlemek ve toplulaştırmaktır. Bu ayrım bir ürünün diğerinden koşulsuz hızlı olduğu anlamına gelmez; sonuç sorgu sınıfına, verinin fiziksel düzenine ve eşzamanlı yüküne bağlıdır.

Üretim ortamında analitik sorgu ile işlemsel sorgu aynı sunucu üzerinde eşzamanlı çalıştırıldığında CPU ve G/Ç kaynakları paylaşıldığı için analitik sorgu doğrudan kilit üretmese bile işlemsel gecikmeyi yükseltebilir. Bu etki özellikle disk kuyruğu, tampon önbelleği tahliyesi, bellek tahsisleri ve iş parçacığı zamanlaması üzerinden görülür. Kaynak izolasyonuna karar vermek için bağımsız OLTP yükündeki p95/p99 işlem gecikmesi ile analitik yük eklendiğindeki dağılım karşılaştırılmalıdır. Ayrı ClickHouse katmanına taşınan sorguların kaynak üzerindeki CPU düşüşü, CDC connector tarafından yapılan log okumasının ve ilk anlık görüntünün I/O maliyetiyle birlikte ölçülür. HTAP yaklaşımı farklı mimarilerle gerçekleştirilebildiğinden "tek veritabanı" ve "tek fiziksel veri kopyası" ifadeleri eşanlamlı değildir. Sorgu anlık görüntü tutarlılığı sağlansa bile OLAP hedefinde en son Oracle işlem onayının henüz bulunmaması mümkündür. Tutarlılık gereksinimi sıklıkla "en fazla x saniye eski veri" gibi bir zaman hedefinden daha güçlü, örneğin "belirli SCN'ye kadarki bütün kayıtların bulunması" biçiminde kurulmalıdır.

### 1.1. İşlemsel ve Analitik Sorguların İş Yükü Özellikleri

İşlemsel sorgunun fiziksel maliyeti çoğu zaman dar bir indeks yoluna ve az sayıda satıra yoğunlaşır; analitik sorgu ise çok daha geniş bir veri bölgesini tarayıp süzer ve özetler. Aynı SQL dili kullanılsa bile depolama ve yürütme tasarımını belirleyen temel fark budur.

![İndeks üzerinden noktasal OLTP okuma ve güncelleme yolu animasyonu](https://alikoker.com.tr/svg/oltp-index-point-update-path.svg "OLTP noktasal okuma ve güncelleme yolu")
![OLAP tarama, filtreleme ve toplulaştırma animasyonu](https://alikoker.com.tr/svg/olap-scan-filter-aggregate.svg "OLAP tarama, filtreleme ve toplulaştırma")


Bir hesap bakiyesi güncellemesi belirli kaydın bulunmasını ve yeni değerin işlem sınırında görünür olmasını gerektirir. Buna karşılık bir milyar olay kaydının saatlere göre sayılması, pek çok satırın yalnız zaman ve tür sütunlarının okunmasını gerektirir. İş yükü tanımı; okuma/yazma oranı, seçicilik, sonuç kardinalitesi, eşzamanlı kullanıcı sayısı ve veri tazeliği gereksinimlerini birlikte içerir.

Bir sorgunun OLTP niteliği yalnız `SELECT` kullanmasına bağlı değildir. Tekil birincil anahtar erişimi, rastgele veri sayfası okuması ve kısa kilit tutma süresiyle tanımlanan sorgu; `SELECT` olsa bile OLTP profili sergiler. Buna karşılık `INSERT INTO ... SELECT` ile milyarlarca kayıttan özet üretimi yazma içerse de analitik karakterdedir. Tasarım öncesinde sorgu günlüğünden satır başına işlenen bayt, seçilen kayıt oranı, eşzamanlılık ve sorgu süresi dağılımı çıkarılır. Bu dağılım, sistem seçimini ürün adından daha güvenilir biçimde yönlendirir.

### 1.2. ACID, İzolasyon, Eşzamanlılık ve Veri Tutarlılığı

ACID yalnız soyut bir özellik listesi değildir. Atomiklik birden çok değişikliğin tek sonuç olarak görünmesini, izolasyon ise eşzamanlı okuyucu ve yazıcıların hangi sürümleri görebildiğini belirler. MVCC, okuyucuyu uzun yazma işlemlerinden ayırmanın yaygın yollarından biridir.

![Transaction commit ve rollback atomikliği animasyonu](https://alikoker.com.tr/svg/acid-transaction-commit-rollback.svg "Transaction commit ve rollback")
![MVCC snapshot ve sürüm görünürlüğü animasyonu](https://alikoker.com.tr/svg/mvcc-snapshot-version-chain.svg "MVCC snapshot ve sürüm görünürlüğü")


Atomiklik, tutarlılık, izolasyon ve kalıcılık birbirinden ayrı garantilerdir. Analitik kopyanın belirli bir INSERT bloğunu atomik görmesi, kaynak OLTP sistemindeki çok tablolu işlemi aynı sınırlarla temsil ettiği anlamına gelmez. Kaynak işlemlerin işlem onay sırası, CDC yeniden oynatımı ve hedefteki sorgunun gördüğü sürüm ayrıca modellenir.

ACID'in C harfi, veritabanı tarafından tanımlanmış bütünlük kısıtlarının korunmasıdır; tüm uygulama doğruluğunun veritabanınca garanti edildiği anlamına gelmez. İzolasyon için serializable, anlık görüntü ve read committed kavramları birbirinin yerine kullanılamaz. Bir OLTP transaction'ının CDC üzerinden birden fazla analitik tabloya yansıtılması sırasında her hedef tablonun kendi yazma atomikliği olabilir; bu, kaynak işlemin hedefte aynı anda görünmesini sağlamaz. Bu nedenle analitik raporun kesit tutarlılığı kaynak işlem onay sırası ve hedefe uygulanmış değişikliklerin ilerleme bilgisiyle değerlendirilir.

### 1.3. OLTP–OLAP Karşılaştırmalı Maliyet Modeli

Maliyet modelini yalnız satır sayısıyla açıklamak yeterli değildir. Okunan bayt, seçilen sütunlar, seçicilik, sıkıştırma, CPU işi ve düğümler arası koordinasyon birlikte toplam maliyeti belirler. Budama ve veri atlama mekanizmalarının değeri de bu fiziksel iş miktarını azaltmalarından gelir.

![OLTP ve OLAP fiziksel veri erişim maliyeti animasyonu](https://alikoker.com.tr/svg/oltp-olap-bytes-touched-cost.svg "OLTP–OLAP fiziksel maliyet")
![Seçicilik ve tarama maliyeti eğrisi animasyonu](https://alikoker.com.tr/svg/selectivity-scan-cost-curve.svg "Seçicilik ve tarama maliyeti")


İşlemsel sorgunun maliyeti yaklaşık indeks araması, sınırlı rastgele G/Ç, kilitleme ve günlük yazımından oluşur. Analitik taramada toplam okunan sütun baytı, ayrıştırma/sıkıştırma maliyeti, hash agregasyonu ve ağda taşınan ara sonuç belirleyicidir. Basit bir tarama için T ≈ B_okunan / β_etkin + T_CPU + T_iletişim; bu toplamsal ifade kaynakların örtüşmesini ihmal ettiği için üst düzey bir tahmindir.

Örnek: Bütün kayıtları `WHERE id = ?` ile tekil getiren bir işlem ile `GROUP BY toStartOfHour(event_time)` hesaplayan sorgunun maliyeti karşılaştırılsın. Birincisi uygun indeksle küçük sayıda sayfa okurken ikincisi gereken sütunları geniş aralıkta işler. 10⁹ kayıt × 8 bayt zaman + 4 bayt kategori + 4 bayt sayaç alanı, sıkıştırma ve indeks budaması yok sayılırsa yaklaşık 16×10⁹ bayt ham okuma demektir. Sekiz alanın yalnız üçünü kullanmak satırdaki diğer alanları okumamayı mümkün kılar. 2 GB/s sürdürülebilir bant genişliği altında sırf ham aktarım alt sınırı yaklaşık 8 saniyedir; disk önbellek, sıkıştırma, paralellik ve eşzamanlı yük gerçek süreyi değiştirir. Bu hesap, milisaniyelik bir sorgunun her koşulda mümkün olduğunu değil, **okunan baytın** birinci derece değişken olduğunu gösterir.

Bir analitik sorgunun maliyeti yalnız satır sayısıyla açıklanamaz. `R` toplam satır sayısı, `c` seçilen sütun sayısı, `bⱼ` j'inci sütunun sıkıştırılmış ortalama bayt değeri, `f` veri atlama sonrasında taranacak satırların oranı ve `β` sürdürülebilir okuma bant genişliği olsun. İlk yaklaşımda depolamadan taşınan bayt sayısı `B ≈ R × f × Σⱼbⱼ` olur. Bu eşitlik seçiciliğin sütunlara göre farklı olmasını, işaret sınırlarını ve fiziksel sıkıştırma bloklarının fazladan okunmasını ihmal eder. Diskten okuma için `T_IO ≥ B/β`; işlemci süresi için `T_CPU ≥ I/ρ` sınırları yazılabilir. Burada `I` çalıştırılan ilgili komutların toplamı, `ρ` sürdürülebilir komut işleme hızıdır. Gerçek yürütme sırasında disk ve CPU örtüşebildiğinden `T ≈ max(T_IO,T_CPU) + T_sıralama + T_ağ + T_sabit` modelinin bazı yürütme planlarında toplamsal modelden daha uygun olduğu görülür.

Bir milyar satırdan oluşan olay tablosunda her satır için yalnız 8 baytlık zaman ve 2 baytlık durum alanı okunduğunu düşünelim. Sıkıştırmasız ve filtre budamasız ham veri 10 GB'dir. Kullanılan iki sütunun birlikte 4 kat sıkıştırılabildiği varsayılırsa 2,5 GB'lik okuma ortaya çıkar. İlgili sorgu `ORDER BY` sayesinde verinin yüzde 2'sini okuyorsa basitleştirilmiş tahmin 50 MB olur; gerçekte asgari granül aralıkları ve blok sınırları nedeniyle bu değerin üzerine çıkılabilir. İndeksin etkisi bu nedenle satır sayısı azaltma yüzdesi değil **fiilen okunmuş bayt** ile doğrulanır.

OLTP ve OLAP kıyaslamasında sistemlerin eşit semantiğe sahip sonuçlar üretmesi zorunludur. Bir sistemde önceden hesaplanmış özet, diğerinde ham veri taraması kullanılması açıklanmayan bir algoritmik avantaj yaratır. Bununla birlikte üretim amaçlı karşılaştırmada sistemlerin doğal fiziksel optimizasyonlarından yararlanmak meşrudur; başarım karşılaştırması raporu veri modelini ve hazırlık maliyetini birlikte vermelidir.

### 1.4. HTAP ve Çok İş Yüklü Mimariler

HTAP tasarımındaki kritik soru, iki iş yükünü aynı düğümde çalıştırmak değil, transactional doğruluk ile analitik erişim gereksinimlerini hangi kaynak sınırlarında birleştireceğidir. Değişiklik akışıyla ayrıştırılmış mimari, büyük taramaların işlemsel kuyruğu bozmasını önleyebilir.

![HTAP değişiklik akışı ve iş yükü ayrıştırma animasyonu](https://alikoker.com.tr/svg/htap-change-stream-separation.svg "HTAP değişiklik akışı ve iş yükü ayrıştırma")
![Karma iş yükünde CPU bellek ve GÇ çekişmesi animasyonu](https://alikoker.com.tr/svg/mixed-workload-resource-contention.svg "Karma iş yükü kaynak çekişmesi")


HTAP aynı altyapıda işlemsel ve analitik yükleri birleştirmeyi hedefler; ayrı motorlu ve ayrı kopyalı mimariler ise kaynak izolasyonunu artırabilir. Aynı veri üzerinde farklı kopyalar kullanılması tazelik gecikmesi ve eşleştirme doğruluğu sorumluluğunu doğurur. HTAP seçimi sıfır gecikmeli analitik garantisi değil, iş yükleri arasında tasarım ödünleşimidir.

Bir HTAP sisteminde aynı SQL arabirimini sunmak, işlemsel ve analitik yürütmenin aynı indeks ve bellek yapısını kullandığını zorunlu kılmaz. Satır biçimli yazma katmanı ile sütun biçimli analitik kopya aynı ürün içinde de ayrı ürünlerde de bulunabilir. HTAP tasarımında belirleyici maliyet, değişikliklerin analitik gösterime aktarılmasındaki gecikme, replikasyon yükü, indeks güncelleme maliyeti ve çakışan kaynak tüketimidir. OLTP'den OLAP'a sürekli aktarım için CDC kullanıldığında kaynak loglarının tutulma süresi ve ilk yükleme kapasitesi de sistem sınırı olarak tanımlanmalıdır.

### 1.5. Gecikme, İşlem Hacmi, Veri Tazeliği ve Sorgu Karmaşıklığı

Analitik sistemde veri tazeliği açık bir zaman sınırıyla tanımlanmalıdır. Kaynak başı ile analitik kopyanın uyguladığı watermark arasındaki fark gerçek lag değeridir. Batch büyütmek işlem hacmini artırabilir; ancak tek olay gecikmesini ve görünürlük süresini de değiştirebilir.

![CDC watermark ve veri tazeliği gecikmesi animasyonu](https://alikoker.com.tr/svg/cdc-freshness-watermark-lag.svg "CDC watermark ve veri tazeliği gecikmesi")
![Gecikme işlem hacmi ve veri tazeliği dengesi animasyonu](https://alikoker.com.tr/svg/latency-throughput-freshness-tradeoff.svg "Gecikme, işlem hacmi ve veri tazeliği dengesi")


Gecikme tek sorgunun tamamlanma süresidir; işlem hacmi birim zamanda tamamlanan sorgu veya işlenen olay sayısıdır. Yük arttığında kuyruklanma p95/p99 gecikmesini yükseltebilir. Tazelik, kaynakta onaylanmış olayın analitik sonuçta görünmesine kadar geçen süredir; veri alımı gecikmesi ile sorgu gecikmesi birbirine karıştırılmamalıdır.

N eşzamanlı sorgu için tamamlanma hızı λ ve ortalama sistemde kalma süresi W ölçülebilir. Kararlı bir kuyruk sisteminde Little yasası L = λ × W bağıntısını verir; burada L ortalama sistem içi sorgu sayısıdır. Bu ilişki yalnız kararlı durum ve tutarlı gözlem penceresi koşullarında kullanılır. Ortalama gecikme azalırken p99'un yükselmesi, nadir büyük taramaların veya bellek taşmalarının kuyruk sonunu etkilediğini gösterebilir. Tazelik metriği ise en son işlenmiş kaynak olayının işlem onayı zamanı ile analiz anı arasındaki farkı, kaynak saat senkronizasyonu ve işlem sırasını dikkate alarak raporlar.

### 1.6. İşlemsel Doğruluğun Kaynağı ve Analitik Kopyanın Sorumlulukları

Analitik kopyanın hızlı olması onu otomatik olarak doğruluğun kaynağı yapmaz. İşlemsel kaynak commit sırası ve iş kurallarını korurken analitik kopya yeniden üretilebilir olmalı; belirli watermark noktalarında satır sayısı, toplamlar veya uygun checksum değerleriyle uzlaştırılabilmelidir.

![Source of truth ve analitik kopya uzlaştırma animasyonu](https://alikoker.com.tr/svg/source-of-truth-reconciliation.svg "Source of truth ve analitik uzlaştırma")


Oracle, PostgreSQL veya MySQL işlemsel doğruluğun kaynağı olmayı sürdürebilir. ClickHouse analitik sorguların yönlendirildiği yeniden üretilebilir bir kopya olabilir. Kayıt kimliği, zaman damgası ve değişiklik sıralaması tanımlanmadan iki sistem arasında tutarlı karşılaştırma yapılamaz; hedefteki silme ve düzeltmeler CDC sözleşmesinin parçasıdır.

Analitik kopyanın yeniden kurulabilir olması için ilk anlık görüntünün hangi kaynak kesitine ait olduğu, değişiklik akışının başlangıç konumu ve her tablonun dönüşüm sürümü saklanır. Belirli bir işlemin aynı anda iki tabloda gözlenmesi gerekli ise salt gecikme ölçüsü yeterli değildir. Hedef sorgularda kullanılabilecek watermark, olayların sırasıyla ve kayıpsız işlendiğini temsil etmelidir. Kaynakta uygulanan silmelerin hedefe aktarılmaması, işlem doğruluğu korunmuş görünse bile tarihsel sayımları ve güncel durum raporlarını hatalı hale getirir.

Analitik kopyanın gecikmesini yalnız zaman farkıyla ölçmek, aynı kaynak işleminin birden fazla tabloya yazıldığı durumlarda eksiktir. `source_transaction_id`, kaynak işlem onay sırası, aktarımın hedefte onaylanan son konumu ve ham veri kümesi sürümü gibi alanlardan oluşturulan işleme sözleşmesi, tekrar oynatımın güvenilir temelidir. Bir sorgu için gerekli eşik `S_req`, hedefin eksiksiz uyguladığı kaynak konumu `S_applied` ise sonuç ancak `S_applied ≥ S_req` ve ilgili bütün kaynak akışlarının kapsandığı doğrulandığında o eşik için tam sayılabilir. Kafka'nın ayrı partition'larında bulunan mesajlara ait ilerleme konumları tek skaler değerle temsil edilemeyebilir; bu durumda her bölüm için ayrı watermark tutulur.

Gerçek zamanlılık ile kesin güncellik farklı kavramlardır. CDC gecikmesi iki saniye olsa bile kaynakta değişmiş bir boyut alanı ile hedefe daha önce ulaşmış olayın birleştirilmesi tarihsel olarak yanlış bir sonuç üretebilir. Raporların tutarlılığı için olay zamanına göre boyut sürümü çözümlemesi veya kaynak işleme göre eşik uygulanması gerekir.

## Ünite 2: ClickHouse: Tarihsel Gelişim, Kurulum ve İlk Kullanım

ClickHouse, Yandex.Metrica'nın yüksek hacimli analitik gereksinimlerinden doğmuş, 2016 yılında açık kaynak olarak yayımlanmış C++ tabanlı sütun yönelimli OLAP sistemidir. Açık kaynak sunucu ile yönetilen bulut hizmeti farklı maliyet ve operasyon sorumluluklarına sahiptir. Dersin uygulamaları için sürüm sabitlenmeli; SQL fonksiyonu veya yapılandırma ayarının tüm sürümlerde bulunduğu varsayılmamalıdır.

Bir ClickHouse kurulumunun verimliliği yalnız `clickhouse-server` sürecinin çalışmasına bağlı değildir. Veri parçası yazımları için kalıcı dosya sistemi, replikasyon için Keeper, sürücüler için aynı SQL özellik kümesi ve veri alım istemcileri için ağ zaman aşımı sözleşmesi gereklidir. Tek düğümlü denemede başarılı çalışan CREATE TABLE örneği yüksek yükte veri parçası birikimi ve birleştirme doygunluk ihtimalini sınamaz. Laboratuvar verisiyle en az INSERT, SELECT, restart sonrası görünürlük, yedekleme ve restore akışı denenmelidir. Container imajı sürüm etiketi sabitlenmediyse aynı compose dosyası daha sonra farklı davranışla sonuçlanabilir. Feature sürüm kayıtları, eski kitapların önerdiği ayarların ve işlem modellerinin neden yeniden incelenmesi gerektiğini gösterir. `UPDATE` patch veri parçası ve projection yenilikleri bu değişimin örnekleridir.

### 2.1. Yandex.Metrica, Açık Kaynak Gelişimi ve 2024 Akademik Çalışma

Çekirdek tasarım, olay verileri üzerinde seçici okuma ve hızlı agregasyonu amaçlar. Schulze ve diğerlerinin 2024 PVLDB makalesi fiziksel depolama, sorgu yürütme ve dağıtık yapı için temel mimari referanstır. Tarihsel yazılar ile güncel uygulama davranışı sürüm belirtilerek ayrılır.

ClickHouse'un kökeni Yandex.Metrica'nın yüksek hacimli olay raporlarını düşük gecikmeyle işleme gereksinimidir. Sistem 2016'da açık kaynak olarak yayımlanmış, daha sonra bağımsız şirket ve topluluk geliştirme süreçleriyle olgunlaşmıştır. 2024 PVLDB yayını, ürün tanıtımının ötesinde depolama mimarisi, yürütme modeli ve dağıtık işleyiş için akademik birincil dayanak sağlar. Tarihsel gelişim anlatılırken yeni sürümlerde eklenen güncelleme, indeks veya optimizer yetenekleri başlangıçtaki sürümlere atfedilmez.

### 2.2. ClickHouse Açık Kaynak Sürümü, Cloud Hizmeti ve Lisanslar

ClickHouse'un açık kaynak sunucu dağıtımı Apache 2.0 lisansıyla sunulur. Bu lisans, yazılımın kullanım ve dağıtım koşullarını düzenler; donanım, barındırma, depolama, güvenlik, yedekleme ve işletim maliyetlerini ortadan kaldırmaz. ClickHouse Cloud ise işlem gücü, depolama, veri aktarımı ve hizmet koşulları üzerinden değerlendirilen yönetilen bir hizmettir. Aynı SQL ve tablo motoru kavramlarını paylaşmak, iki dağıtımın ağ, güvenlik, nesne depolama ve operasyon özelliklerinin bütünüyle aynı olduğu anlamına gelmez.

Lisans uyumluluğunda en az üç nesne ayrı değerlendirilir: sunucu kaynak kodu, resmi dokümantasyon ve uygulamayla dağıtılan üçüncü taraf bağımlılıklar. Kaynak koduna ait Apache 2.0 koşulları, belgelerin Creative Commons koşullarına otomatik uygulanmaz. Kurumsal sahip olma maliyeti de yalnız lisans bedeliyle hesaplanmaz: yıllık maliyet = işlem kaynakları + kalıcı depolama + replikasyon + yedekleme + ağ aktarımı + bakım emeği + hizmet kesintisi riski. Karşılaştırılan seçeneklerde veri hacmi, saklama süresi, kurtarma hedefi ve hizmet düzeyi eşit tutulmalıdır.

### 2.3. Linux/Windows İstemcisi, Konteyner ve Dağıtımlar

Sunucu üretimde sıklıkla Linux üzerinde çalıştırılır; istemciler farklı işletim sistemlerinden bağlanabilir. Konteyner tek başına kalıcılık ve güvenilirlik garantisi sağlamaz. Volume, memory limit, CPU quota, dosya izinleri, ağ ve saat eşleştirmesi kurulum tasarımının parçasıdır.

Deney ortamında Docker üzerinden tek düğüm başlatmak yeterli olabilir; kalıcı veri dizininin volume ile bağlanması, servis hesabının dosya sahipliği ve dosya tanıtıcı sınırı ayrıca doğrulanmalıdır. Üretimde yalnız container'ın yeniden başlaması veri güvenliği sağlamaz. Bellek sınırları ile ClickHouse'un sorgu bellek limitlerinin uyumlu kurulması gerekir; host üzerindeki bellek yetmezliği nedeniyle çalışan süreç öldürülebilir. Kaynak tüketiminde cgroup ile sunucu içi kota farklı katmanlardır.

### 2.4. Sunucu Süreçleri, Sürüm ve Uyumluluk Politikası

Çekirdek server süreci depolama, sorgulama ve arka plan görevlerini birlikte yürütür. Yükseltmeden önce uyumluluk notları, yedek, konfigürasyon testi ve geri dönüş koşulları tanımlanır. Sürüm geçişinde deneysel ayarlar ve tablo formatı davranışları ayrıca gözden geçirilir.

Sürüm yükseltmesinde yalnız uygulama SQL'inin yeniden çalışması değil veri parçası dosya biçimi, Keeper uyumluluğu, değişen ayar varsayılanları ve istemci sürücüleri sınanır. Geri dönüş planı, yeni sürümün yazdığı üstveri veya veri parçası biçimini önceki sürümün okuyabildiği varsayımına dayanamaz. Yükseltme öncesi geri yükleme testi yapılmış yedek, geriye dönük uyumluluk notları ve kontrollü replikasyon sırası gerekli olabilir.

22 Ekim 2026 tarihli resmi sürüm sunumunda 26.10 dalı duyurulmuştur. Resmi paket deposuna göre 27 Ekim 2026 itibarıyla kararlı kanal 26.10.3.7 (25 Ekim), LTS kanalı ise 26.8.36.3 (26 Ekim) sürümündedir. Kararlı ve LTS kanalları farklı yükseltme ve bakım tercihlerini temsil eder; sürüm numarası tek başına kullanılan SQL özelliklerinin varsayılan olarak açık olduğunu göstermez. Özellikle deneysel bir ayar gerektiren işlevler, standart kurulumun değişmez parçası sayılmamalıdır. [41, 42]

ClickHouse 26.8, Eylül 2026'da uzun süreli destek (LTS) sürümü olarak yayımlanmıştır. 26.9 ve 26.10'un yeni özelliklerinden önce bu sürümle gelen arka plan sorguları, pipelined SQL, `system.user_query_log` ve veri gölü okuyucularındaki iyileştirmeler değerlendirilmelidir. LTS statüsü belirli bakım ve düzeltme politikalarını ifade eder; daha yeni bir kararlı sürümün bütün işlevlerini içerdiği veya hiçbir davranış değişikliğine uğramadığı anlamına gelmez. Kararlı ve LTS sürümleri arasındaki tercih için istemci sürücülerinin destek matrisi, geri dönüş imkanı, güvenlik düzeltmeleri ve özelliklerin deneysel olup olmadığı birlikte incelenir. [46]

### 2.5. Tek Düğüm Laboratuvar Kurulumu ve ClickHouse-client

Tek düğümlü kurulumda `SELECT version()` ve `SELECT * FROM system.build_options LIMIT 10` sistem tanılamasının başlangıç örnekleridir. `clickhouse-client` bağlantı, SQL yürütme ve çıktı formatları sağlar. Laboratuvar verisinin yeniden üretilebilir olması için şema ve yükleme komutları kayıt altına alınır.

Sürümü ve sunucu yapılandırmasını doğrulamak için kısa sorgular:

```sql
SELECT version();
SELECT name, value FROM system.settings WHERE name IN ('max_threads', 'max_memory_usage');
SELECT name, value FROM system.build_options LIMIT 10;
```

Sorgu sonuçları laboratuvarda kullanılan sürümle birlikte saklanır; farklı sürümde elde edilen plan aynı deneyin tekrarı sayılmaz.

Tek düğümlü denemede yazma, okuma ve yeniden başlatma döngüsü, motorun veri kalıcılığını ve istemci ayarlarını doğrulamalıdır. Kaynak tabloların anahtar, codec ve bölüm tanımları başlangıçta küçük örneklerle sınanır. `system.tables` üzerinden motor ve şema, `system.parts` üzerinden aktif MergeTree veri parçalarını incelenebilir. Dış bağlantı yoksa deneyin başarısı yalnız süreç başlangıcını değil bütün bağımlılıkların erişilebilirliğini kapsar.

```sql
CREATE DATABASE IF NOT EXISTS olap_lab;

CREATE TABLE IF NOT EXISTS olap_lab.measurements
(
    measured_at DateTime64(3, 'UTC'),
    device_id UInt32,
    reading Float64
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(measured_at)
ORDER BY (device_id, measured_at);

INSERT INTO olap_lab.measurements VALUES
('2026-10-27 10:00:00.000', 1, 3.5),
('2026-10-27 10:00:01.000', 1, 4.5),
('2026-10-27 10:00:00.000', 2, 7.0);

SELECT device_id, count() AS samples, avg(reading) AS mean_reading
FROM olap_lab.measurements
GROUP BY device_id
ORDER BY device_id;
```

Örnek tablonun birincil anahtarı benzersiz değildir; aynı cihaz ve zaman için aynı kayıt tekrar eklenirse iki satır görünür. Kalıcı laboratuvar verisinde INSERT'in yinelenmesi ve aynı şemanın tekrar çalıştırılması ayrı konulardır. `CREATE TABLE IF NOT EXISTS` şemayı korurken yinelenen `INSERT VALUES` işlemini tekilleştirmez. Gerçek testte kaynak verinin tekrarlı teslim özelliği ölçülür.

### 2.6. Güncelleme, Sürüm Yükseltme ve Yapılandırma Doğrulama

Rolling upgrade replikalı kurulumlarda düğümlerin uyumluluk aralığına ve parça formatlarına bağlıdır. Yedek başarıyla oluşturulmadan yapılan yükseltme geri dönüş güvencesi değildir. Ayrık test kümesinde kurulum, sorgu ve restore denemesi tamamlanmalıdır.

Düğüm yükseltmesi sırasında sorgu yönlendirme, replika gecikmesi ve arka plan birleşme kuyruğu izlenmelidir. Aynı kümeye karışık sürümlerle hizmet verilebilen süre sürüm uyumluluk sözleşmesine bağlıdır. Bir ayar adının yeni sürümde kabul edilmesi, davranışının değişmediğini garanti etmez; hedef sorgular için sonuç eşitliği ve performans regresyonu sınanır. Kritik şema dönüşümleri önce geri dönüşü mümkün küçük veri kesitlerinde denenmelidir.

### 2.7. ClickHouse Komut Satırı ve SQL Arayüzleri

Yerel istemci, HTTP sorguları, web SQL arayüzleri ve üçüncü taraf araçları aynı sorgu motoruna ulaşabilir; fakat zaman aşımı, format, oturum ve auth davranışları farklıdır. Karşılaştırmalı testte istek protokolü ve istemci sürümü belirtilir.

`clickhouse-client` sunucuya bağlı sorgular için kullanılırken `clickhouse-local` yerel dosyalar üzerinde ayrı sunucu kurmadan analiz yapabilir. Bir SQL konsolunun desteklediği oturum ayarlarıyla komut satırının varsayılanları farklı olabileceğinden aynı sorgunun performansı doğrudan kıyaslanmamalıdır. Büyük sonuçların terminalde gösterilmesi de client-side aktarım ve biçimlendirme maliyeti üretir; başarım karşılaştırması için sonuç yükü sabit tutulur.

## Ünite 3: ClickHouse Veri Türleri ve Şema Tasarımı

Analitik tabloda sütun tipi depolama boyutunu, karşılaştırma maliyetini ve sorgu doğruluğunu birlikte etkiler. Gerçekte yalnız pozitif ve sınırlı değer taşıyan bir alan için uygun UInt türü daha küçük veri temsili sağlayabilir; fakat taşma ve kaynak şema değişikliği hesaba katılmalıdır. Finansal kesinlik gerektiren miktarları Float ile toplamak ikili yuvarlama sonuçları doğurabilir. ClickHouse tür sistemi, Nullable ile karmaşık JSON ve nested değerlere kadar uzanır.

Veri tipi tasarımının maliyet etkisi bir milyar satırlı veri kümesinde belirginleşir. Değeri 0–65.535 aralığında kalan bir ölçüm UInt64 yerine UInt16 olarak saklanırsa sıkıştırma öncesinde sütun başına 6 milyar byte fark doğar. Gerçek sıkıştırılmış fark veri dağılımına göre değişir. 32-bit timestamp ile milisaniye hassasiyetli DateTime64 aynı alanı temsil etmez; veri doğruluğu kaybı yalnız depolama tasarrufuyla savunulamaz. Kimlik, zaman, miktar ve durum alanları için önce aralık ve semantik tanımı yapılmalı, sonra tür belirlenmelidir. JSON içinde saklanan yüksek hacimli sorgu alanlarının tipli kolonlara taşınması ayrıştırma maliyetini azaltabilir; esnek yapı gerektiren seyrek özellikler için JSON alt alanları kullanılabilir.

### 3.1. Sayısal Türler, Decimal, Float ve Taşma Semantiği

UInt8/16/32/64 alanın gerçek aralığına göre seçilir. Decimal sabit ondalık ölçekle finansal hesaplarda yararlıdır; Decimal işlemlerinin taşma ve ölçek davranışları incelenmelidir. Float32/64 yaklaşık gösterimdir; `(0.1 + 0.2) == 0.3` gibi eşitlikler kayan nokta semantiğinde güvenilir test değildir.

Sayı türü seçiminde minimum/maksimum değer, negatif değer olasılığı ve aritmetik taşma birlikte ele alınır. `Float32` hesaplarında ikili kayan nokta temsilinden dolayı ondalık parasal değerler tam saklanmayabilir; `Decimal` ölçekli tamsayı temsili sunar. Ancak `Decimal` de seçilen precision/scale sınırları içinde kullanılmalı ve işlemlerde taşma/yuvarlama davranışı sınanmalıdır. Yüz milyarlarca satırda gereksiz 64 bit genişlik kullanmak sıkıştırma sonrasında da CPU/önbellek maliyeti yaratabilir.

### 3.2. String, FixedString, LowCardinality, Enum

`String` değişken uzunluğu, `FixedString(N)` sabit uzunluğu temsil eder. `LowCardinality(String)` sözlük kodlaması sayesinde sınırlı farklı değere sahip kolonlarda depolamayı ve bazı işlemleri iyileştirebilir; çok yüksek kardinalitede ek yük doğurabilir. Enum türleri şema evriminde özel dikkat ister.

`String` değişken uzunluklu veriyi saklarken `FixedString(N)` sabit genişlikli alan gereksinimlerinde kullanılabilir; gereksiz sabit genişlik boş alan tüketebilir. `Enum` sayısal kod ile sınırlı sembol kümesi arasında eşleme sağlar fakat sözlük değerlerini değiştirmek şema yönetimi gerektirir. `LowCardinality` sık tekrarlanan metinsel değerleri sözlük kodlamasıyla temsil edebilir. Alan değerleri neredeyse tümüyle benzersizse düşük kardinalite varsayımı yanlış olur; tür seçimi veri dağılımıyla doğrulanmalıdır.

### 3.3. Date, DateTime, DateTime64 ve Saat Dilimleri

`DateTime64(3, 'UTC')` milisaniye hassasiyetli zaman damgası için uygundur. Timestamp'ın yazıldığı zaman dilimiyle gösterildiği zaman dilimi ayrımı korunmalıdır. `toStartOfHour`, `toDate`, `toYYYYMM` gibi fonksiyonlar saat dilimi ve DST sınırlarında sınanır.

Zaman damgalarını UTC saklamak, raporda her kullanıcının yerel zaman dilimini göstermek için yeterli üstverinin bulunduğu anlamına gelmez. Aynı UTC anı farklı bölgelerde farklı takvim gününe düşebilir. Günlük raporların UTC gününe mi, kullanıcının yerel gününe mi göre kesildiği belirtilmelidir. Yaz saati değişiminin olduğu bölgelerde 02:30 yerel saat tekrarlanabilir veya hiç oluşmayabilir. Tarihsel analizde yerel saatten UTC'ye dönüşüm saat dilimi veritabanının ilgili sürümüne bağlıdır.

`DateTime` saniye, `DateTime64(p)` tanımlanan kesir hassasiyetiyle zamanı temsil eder. Saklanan an ile gösterimde kullanılan saat dilimi ayrıdır; aynı UTC anı İstanbul ve New York oturumlarında farklı duvar saati olarak yazılabilir. Saat dilimi belirtilmeden oluşturulmuş literal'ler sunucu/oturum varsayılanlarına göre farklı yorumlanabileceğinden sorgu örneklerinde `UTC` açıkça kullanılmalıdır. Özellikle gün başlangıcını hesaplayan `toStartOfDay` veya ay bazlı TTL işlemlerinde olay zamanı ve raporlama saat dilimi sözleşmesi gereklidir.

Yaz saati geçişinde yerel bir saat iki kez yaşanabilir veya hiç yaşanmayabilir; bu nedenle yalnız `YYYY-MM-DD HH:MM:SS` metnine bakılarak olay sırası garanti edilemez. Olay kimliği ve UTC anı birlikte saklandığında sıra ve yerel sunum ayrıştırılabilir.

### 3.4. UUID, IPv4/IPv6, Boolean ve Özel Türler

UUID kimlik saklama için kullanılır; rastgele UUID'nin sıralama anahtarında başa alınması lokaliteyi zayıflatabilir. IPv4/IPv6 türleri metinsel ayrıştırmanın yerine tipli adres karşılaştırması sağlar. Boolean gösterimi ve fonksiyon adları sürüme göre kontrol edilir.

UUID ve IP adresi türleri, metinsel gösterim yerine uygun ikili temsile ve ilgili fonksiyonlara olanak sağlar. `IPv4` ile String içinde tutulan noktalı gösterimin sıralama ve karşılaştırma davranışı aynı değildir. Boolean desteği ve `Bool` isimlendirmesi kullanılan ClickHouse sürümüne bağlı olarak doğrulanır. Olay şemasında kimlik, ağ adresi ve ölçüm alanlarının doğru tipte tutulması, hem bellekteki temsilin hem de WHERE koşullarının tür dönüşümü maliyetini etkiler.

### 3.5. Array, Demet, Map, Nested, JSON, Dynamic/Variant Uygunluğu

Array/Map/Demet birleşik alanları temsil eder; Nested satır içi alt yapıların bir düzenidir. JSON, Dynamic ve Variant esnek şema gereksiniminde kullanılır; her sorguda yoğun JSON ayrıştırması yazımda tipli sütuna ayırma kadar verimli olmayabilir. Sürüm olgunluğu ve subcolumn erişimleri incelenir.

ClickHouse karmaşık veri tipleri yapısal esneklik sağlar; sorgu biçimine bakılmadan bütün olayın `JSON` içinde tutulması varsayılan en iyi şema değildir. Sık gruplanan `service`, `status`, `event_time` gibi alanlar türü bilinen sütunlarda tutulduğunda filtreleme ve sıkıştırma maliyetleri daha öngörülebilir olur. Seyrek ve nadiren sorgulanan nitelikler JSON içinde bulunabilir. Bir alanın başlangıçta seyrek olması kalıcı olarak seyrek kalacağı anlamına gelmez; erişim örüntüsü değiştiğinde alanın tanımlı sütuna çıkarılması değerlendirilebilir.

`Array(T)` tek satırda birden fazla değer tutabilir; `arrayJoin` bu değerleri satırlara açarak kardinaliteyi büyütür. `Map(K,V)` dinamik anahtar-değer sorgusu sağlasa da büyük map koleksiyonları gereksiz ayrıştırmaya neden olabilir. `LowCardinality(String)` yaygın tekrarlı kategoriler için sözlük temsili kullanabilir; çok yüksek benzersizlik oranında sözlük yönetimi ek maliyet doğurabilir. Veri tipi kararı ham bayt, sıkıştırılmış bayt, bellek tüketimi ve sorgu yükü temelinde verilir.

ClickHouse 26.10, Parquet ve Iceberg içindeki `VARIANT` temsilinin `Dynamic` olarak okunmasını geliştirmiştir. Fiziksel olarak heterojen değerler taşıyan bir kolonda `dynamicType()` ile gerçek türün incelenmesi, dönüşümün sessiz tip kaybına yol açmaması için önemlidir. `JSON` nesnelerinin iç içe alanlarıyla tarih/sayı türlerinin aynı sütunda yer alması, filtrelerin tür denetimini ve sorgu optimizasyonunu karmaşıklaştırabilir. Şema doğrulamasında `null`, eksik alan, sayısal tür genişlemesi ve tekrarlanmış alan adı vakaları ayrı örneklerle sınanmalıdır. Bu işlev Parquet kaynağı ile MergeTree içindeki her kolonun aynı fiziksel temsilini kullandığı anlamına gelmez. [41]

Analitik tabloda sayısal vektörler `Array(Float32)` gibi tiplerle saklanabilir. Vektör uzunluğu d, satır sayısı N olduğunda yalnız ham Float32 öğeleri yaklaşık 4 × N × d bayt gerektirir; d=768 ve N=10 milyon için 30,72 milyar baytlık ham öğe alanı oluşur. Boyut, ofset, indeks ve kopyalama maliyetleri bu hesaba dahil değildir. HNSW benzeri yaklaşık en yakın komşu indeksleri ek grafik belleği/depolaması tüketerek arama aday sayısını azaltmayı hedefler. ClickHouse'un `vector_similarity` indeksleri için HNSW desteği 25.8 sürümünde genel kullanıma sunulmuştur; indeksin boyut, uzaklık işlevi, nicemleme ve filtreleme koşulları sorgu performansını etkiler. Bu indeksler veri ambarındaki `GROUP BY` veya MergeTree seyrek birincil indeksinin eşdeğeri değildir. [48]

### 3.6. Nullable Maliyeti ve NULL Semantiği

`Nullable(T)` NULL varlığını ifade eder, ek maske ve bazı işlem maliyetleri getirebilir. Kaynakta 0 ile bilinmiyor farklı anlamdaysa NULL'ı kaldırmak semantik hatadır. Varsayılan değer seçimi verinin gerçek anlamı üzerinden yapılır; performans tek karar kriteri değildir.

`Nullable(T)` sütunda NULL varlığını işaretlemek için ek üstveri tutabilir ve bazı sorgu optimizasyonlarını etkileyebilir. SQL'deki NULL bilinmiyor/değer yok semantiğiyle, boş string veya sıfır birbirinin yerine kullanılmamalıdır. `count(x)` NULL olmayan kayıtları sayarken `count()` bütün satırları sayabilir; toplulaştırma fonksiyonlarının NULL davranışları işlenen veriye göre ayrıca sınanmalıdır. Gereksiz Nullable kullanımı yerine kaynağın gerçekten bilinmeyen değer üretebildiği alanlar modellenmelidir.

### 3.7. Varsayılan ve Hesaplanan Sütunlar, Takma Adlar, Kodlayıcılar ve Kısıtlar

DEFAULT yazım veya okuma sırasında değer üretimi, MATERIALIZED hesaplanmış saklı kolon, ALIAS türetilmiş erişim sağlar. Kodlayıcı, constraint ve expression davranışları INSERT/ALTER sırasındaki uyumluluğu etkiler. Kaynak veriyi değiştiren dönüşümlerde açık doğrulama gerekir.

`DEFAULT` ifade verilmediğinde hesaplanacak değeri, `MATERIALIZED` tabloya yazılırken hesaplanan alanı, `ALIAS` ise saklanmayan hesaplanmış alanı temsil eder. `CODEC` depolamadaki dönüştürme/sıkıştırma zincirini belirler. Bu özelliklerin çoğu şema tasarımını etkiler; ilişkisel veritabanlarındaki genel `CHECK`, `FOREIGN KEY` ve `UNIQUE` kısıtlarını birebir karşılar gibi ele alınmamalıdır. Veri doğruluğu kuralları kaynak, ingest hattı ve sorgu sonucunda ayrıca sınanmalıdır.

`ALIAS` ifadesi saklı veri üretmez; sorgu anında türetilen ifade maliyeti yaratabilir. `MATERIALIZED` sütununun geçmiş satırları ALTER sonrasında kendiliğinden aynı fiziksel gösterimi kazanmayabileceği dikkate alınmalıdır. Bu nedenle şema değişikliğini yalnız `DESCRIBE TABLE` çıktısından doğrulamak yetersizdir; eski veri parçalarından ve yeni INSERT'lerden okunan örnekler aynı sorguyla test edilir.

Birim uyuşmazlığı sık rastlanan sessiz hatadır. `latency_ms` alanına mikrosaniye yazılması tip doğrulamasından geçebilir, ancak yüzdelik değerleri bin kat büyütür. `CHECK` ifadeleri belirli satır içi koşulları doğrulayabilse de dış tablo referansları üzerinde OLTP benzeri foreign-key garantisi vermez. Birim sözleşmesi ve referans alanlarının doğruluğu veri alım sınırında ayrıca korunmalıdır.

### 3.8. Şema Çıkarımı ve Şema Evrimi

Parquet/CSV/JSON verisinden tip tahmini NULL yoğunluğu veya ilk örneklerin sınırlı olması nedeniyle yanlış çıkabilir. Şema evriminde yeni kolon default'u, eski veri parçası okuması ve downstream tüketiciler birlikte doğrulanır. Tip daraltması veri kaybına yol açabileceğinden bütün eski değer aralıkları sınanmalıdır.

Kaynak verinin dönüşümden sonraki gerçek türü doğrudan sorgulanabilir:

```sql
SELECT
    toTypeName(toDateTime64('2026-10-27 12:00:00', 3, 'UTC')) AS timestamp_type,
    toTypeName(toUInt32(42)) AS id_type,
    toTypeName(toDecimal64(12.50, 2)) AS amount_type;
```

Şema çıkarımıyla oluşturulan kolonların katalogdaki tipleri bu tür dönüşüm beklentileriyle karşılaştırılır.

Yeni sütun eklenmesi, mevcut part'larda hemen fiziksel yeniden yazım gerektirmeyebilir; veri tipi değiştirme işlemi ise maliyetli mutation başlatabilir. Şema evrimi Kafka/CDC mesajı, ara biçim ve hedef sütun tanımı arasında koordine edilmelidir. Eski kayıtlar için varsayılan değerin semantik olarak gerçek ölçüm mü yoksa bilinmeyen değer mi olduğu belirtilmelidir. Sürüm geçişinde hem eski hem yeni mesaj biçimlerinin işlenebilirliği test edilmeden üretime geçilmemelidir.

Şema evriminde `ALTER TABLE ... ADD COLUMN` işleminin tarihsel veri parçalarını anında fiziksel olarak yeniden yazıp yazmadığı, yeni sütunun varsayılan değeri ve tablo motoru sürümüne bağlıdır. Mantıksal olarak mevcut eski satırlarda görülen default değer ile arka planda fiziksel olarak depolanmış sütun verisi aynı şey değildir. Geri dönüşü zor bir tip daraltması öncesinde min/max aralığı, geçersiz tarih, Decimal scale kaybı, Nullable geçişi ve JSON alt alanlarının türleri doğrulanır.

CDC hattında kaynak alan eklenmesi tek başına güvenli bir genişletme sayılmaz. Bağlayıcının şema sürümü, Kafka mesaj sözleşmesi ve ClickHouse hedef kolonu farklı anlarda değişebilir. Uygun geçiş sırası, eski ve yeni olay biçimlerinin aynı anda kabul edildiği bir uyumluluk penceresi oluşturmaktır. Yalnız tablo DDL'sinin başarılı olması veri hattının uçtan uca doğru çalıştığını kanıtlamaz.

## Ünite 4: ClickHouse SQL ve Temel Veri Tabanı İşlemleri

ClickHouse SQL, bildirimsel sorgulamayı sütun yönelimli analitik operatörlere bağlar. Genel SQL bilgisi geçiş için yararlı olsa da veri tipleri, sıralama, PREWHERE, agregasyon durumları ve motor seçenekleri ClickHouse'a özgü kurallar içerir. Üretim SQL'i sorgu sonucunun doğruluğu kadar yürütme planı ve kaynak sınırları açısından da değerlendirilir.

ClickHouse SQL'inde sorgu sözdiziminin kabul edilmesi, Oracle/PostgreSQL'deki işlemsel ve NULL semantiğinin aynen taşındığı anlamına gelmez. Analitik tabloların birincil anahtar tanımı fiziksel sıralama ve seyrek indeks seçimini belirler; benzersiz anahtar kısıtı değildir. `SELECT *` büyük String/JSON sütunlarını gereksiz okuyabilir; açık projeksiyon hem disk hem ağ maliyetini düşürebilir. `ORDER BY` tablodaki fiziksel düzeni tanımlarken sorgu sonucunun `ORDER BY` ifadesi ayrı bir sıralama işlemi gerektirebilir. `LIMIT 100` kullanılması sonucu sıralamak için milyonlarca satırın incelenmediğini garanti etmez. `PREWHERE`, filtre sütunlarının erken okunması için optimize edilmiş bir mekanizmadır; genel SQL standardına ait bağımsız bir filtre cebiri değildir.

Tablo motorunun seçimi okuma/yazma garantisi, kalıcılık ve hata alanıyla ilişkilidir. `Memory`, geçici ve yeniden üretilebilir ara veri için uygundur; süreç yeniden başladıktan sonra disk kalıcılığı gerektiren kayıtlar için kullanılmaz. `Kafka` motoru akış kaynağıyla tüketim bütünleştirmesine aracılık eder, tek başına üretim analitik saklama deposu değildir. `Distributed` sorguları bölütlere yönlendirebilir ancak yerel fiziksel veri saklamayı kendiliğinden üstlenmez; ilgili yerel tabloların da yönetilmesi gerekir.

Yabancı `MySQL` veya `PostgreSQL` motorlarından yapılan sorgularda uzak sistemin kaynak limitleri, ağ gecikmesi ve pushdown yetenekleri sonucun parçasıdır. ClickHouse SQL'inin hızlı olması yabancı OLTP kaynağındaki sorguyu aynı oranda hızlandırmaz. Gerçek zamanlı sorgu yerine CDC ile yerel MergeTree kopyası oluşturmak sorgu izolasyonu sağlayabilir; buna karşılık tazelik ve iki kopyanın tutarlılığı sorumluluğu getirir.

### 4.1. DDL CREATE/ALTER/DROP/RENAME

CREATE TABLE içinde ENGINE, Bölüm BY, ORDER BY ve TTL depolama tasarımını tanımlar. ALTER TABLE ekleme/çıkarma ve mutation işlemleri yapabilir; büyük tablodaki şema değişimi sürüm ve motor davranışı dikkate alınarak yürütülür. DDL ile veri taşınmasının atomiklik sınırları ayrı değerlendirilir.

`CREATE` şemayı kurar, `ALTER` üstveri veya veri dönüşümünü başlatabilir, `DROP` nesneyi kaldırır, `RENAME` isim eşleştirmesini değiştirir. Bunların işlemsel görünürlüğü genel amaçlı bir OLTP transaction'ının geri alma sözleşmesine benzetilmemelidir. Özellikle `ALTER` ile tetiklenen uzun mutation ile yalnız üstveri değişikliği yapan işlemler farklı maliyetlere sahiptir. Üretimde DDL uygulaması önce sürüm uyumluluğu ve geri dönüş planı üzerinden doğrulanır.

### 4.2. SELECT, WHERE, PREWHERE, ORDER BY, LIMIT

`WHERE` satır koşulunu değerlendirir; `PREWHERE`, seçilen filtre sütunlarını diğer sütunlardan önce okuyarak gereksiz okumayı azaltabilir. Sorgudaki `ORDER BY` sonuç sırasını belirlerken tablo tanımındaki `ORDER BY` fiziksel sıralama anahtarıdır. `LIMIT` operatörünün kaynak okumayı erken durdurabilmesi, sorgudaki sıralama, filtre ve agregasyon işlemlerinin yürütme özelliklerine bağlıdır.

Aşağıdaki olay şemasında durum kodu ayrıca tanımlanmıştır. Örnekler boyunca kullanılan `status_code` alanı böylece `CREATE TABLE`, `INSERT` ve `SELECT` işlemleri arasında tutarlıdır:

```sql
CREATE TABLE events
(
    event_id UUID,
    service_id UInt32,
    event_type LowCardinality(String),
    event_time DateTime64(3, 'UTC'),
    ingested_at DateTime64(3, 'UTC'),
    status_code UInt16,
    duration_ms UInt32,
    bytes_sent UInt64,
    message String
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(event_time)
ORDER BY (service_id, event_time, event_id)
TTL event_time + INTERVAL 365 DAY DELETE;
```

`event_id` birincil anahtar olarak bildirilmediği gibi fiziksel benzersizlik de sağlamaz. Aynı servis ve zaman aralığı üzerinde çok sayıda sorgu yürütülüyorsa sıralama öneki granül atlamaya yardım edebilir; yalnız `event_id` ile yapılan noktasal aramalar için aynı tasarımın uygun olduğu varsayılamaz. Olay zamanına göre TTL kullanılması, geç gelen olayların kayda geçtikleri tarihten bağımsız olarak daha erken temizlenmesine yol açabilir.

ClickHouse 26.9 ile sıralı akışta sınır koşulları uygulayan `LIMIT ... AFTER` ve `UNTIL` biçimleri eklenmiştir. `AFTER` ilk eşleşen satırı içerir, `UNTIL` bitiş koşulunu karşılayan satırdan önce durur. Hata ile sonraki başarı arasındaki olayları seçen sorgu:

```sql
SELECT event_time, event_id, service_id, status_code
FROM events
WHERE service_id = 42
ORDER BY event_time, event_id
LIMIT 25 AFTER status_code >= 500 UNTIL status_code < 500;
```

Bu koşul `WHERE status_code >= 500` ile eşdeğer değildir: sınırın açılmasından sonra hata kodu taşımayan ara kayıtlar da okunabilir. Zaman damgaları aynıysa kararlı bir ek sıralama anahtarı bulunmalıdır. Sınır koşulları 26.9 öncesinde geçerli değildir ve eksik olayları yeniden üretmez. [38]

### 4.3. INSERT SELECT, VALUES ve Veri Biçimi Sözdizimi

`INSERT INTO ... VALUES` küçük ve açık veri yükleri için; `INSERT INTO ... SELECT` sunucu tarafı dönüşüm ve toplu aktarım için; `FORMAT JSONEachRow`, Parquet ve benzeri biçimler dış kaynaktan veri alımı için kullanılır. Aktarım sırasında alan tiplerinin örtük dönüşümü, bozuk satırların reddi ve kısmi hata davranışı açıkça değerlendirilmelidir.

Ünite 4.2'de tanımlanan `events` tablosuna, koşullu `LIMIT` örneğinde kullanılabilecek üç sıralı kayıt eklenebilir:

```sql
INSERT INTO events
    (event_id, service_id, event_type, event_time, ingested_at,
     status_code, duration_ms, bytes_sent, message)
VALUES
    (generateUUIDv4(), 42, 'REQUEST', toDateTime64('2026-10-27 12:00:00', 3, 'UTC'), now64(3), 200, 42, 4096, 'completed'),
    (generateUUIDv4(), 42, 'ERROR',   toDateTime64('2026-10-27 12:01:00', 3, 'UTC'), now64(3), 503, 900, 0, 'timeout'),
    (generateUUIDv4(), 42, 'REQUEST', toDateTime64('2026-10-27 12:02:00', 3, 'UTC'), now64(3), 200, 37, 2048, 'recovered');
```

Bu kayıtlarla sınır sorgusu 12:01'de başlayan hata penceresini seçer; 12:02'deki başarılı isteği dışarıda bırakır. `generateUUIDv4()` her çalıştırmada farklı kimlik ürettiğinden yeniden yürütme yeni fiziksel satırlar oluşturur. Dolayısıyla örnek, idempotent veri alımı veya güvenli geçmiş veri yüklemesi prosedürü değildir.

Büyük aktarım aralıklar halinde yapıldığında anahtar ya da zaman sınırları ayrık tanımlanmalıdır: `[t₀,t₁)`, `[t₁,t₂)` gibi yarı açık aralıklar boşluk ve çakışmayı önlemeye yardımcı olur. Kaynak aynı anda değişiyorsa tek başına zaman filtresi anlık görüntü tutarlılığı sağlamaz. Doğrulama `service_id`, gün, olay türü ve durum kodu dağılımı üzerinden sayım ve toplam süre karşılaştırmalarını içerir. `uniqExact(event_id)` fiziksel mükerrerleri gösterebilir; olay kimliğinin gerçekten kaynakta benzersiz olduğu varsayımı ayrıca doğrulanır. [7, 8]

### 4.4. DISTINCT, SAMPLE, UNION/INTERSECT/EXCEPT

DISTINCT tüm aday sonuçlardaki benzersiz kombinasyonları hesaplar; SAMPLE uygun tablo örnekleme anahtarıyla tahmini analiz destekler. UNION, INTERSECT, EXCEPT ve ALL/DISTINCT davranışları SQL lehçesi ve sürüme bağlıdır. Örnekleme yanlılığı özellikle nadir olayların incelenmesinde önemlidir.

`DISTINCT` çok sayıda farklı sonuç anahtarı oluştuğunda bellek maliyetini yükseltir. `SAMPLE` yalnız uygun örnekleme ifadesiyle kurulmuş tablolarda anlamlıdır; rastgele örneklem varsayımı fiziksel anahtar dağılımı incelenmeden kabul edilmemelidir. `UNION ALL` kayıtları korurken `UNION DISTINCT` tekrarları ayıklar ve fazladan işlem gerektirebilir. Bir `LIMIT` kullanılması her sorguda gereken okuma miktarını azaltmaz; `ORDER BY` ve filtre sıralaması yürütme planına bağlıdır.

`DISTINCT`, gerçek benzersizliği hesaplamak üzere büyük sayıda anahtar saklayabildiğinden grup kardinalitesi arttığında bellek tüketimi ciddi bir sınıra dönüşür. 26.9 sürümünde yüksek kardinaliteli `DISTINCT` işlemleri için ara durumların diske taşınması geliştirilmiştir. Disk taşması semantiği yaklaşık sayım algoritmasına dönüşüm değildir: sonuç yine kesin olabilir; fakat sıralama, bölümleme ve geçici dosya G/Ç maliyeti artar. Bu özellik ile `uniq` gibi yaklaşık agregasyonların hata/bellek değiş tokuşu karıştırılmamalıdır.

Tam benzersiz değerlerin listelendiği `SELECT DISTINCT user_id` ile yalnız sayısının istendiği `SELECT uniqExact(user_id)` farklı sonuç türleridir. `uniq(user_id)` ise yaklaşık sayım sağlayabilir. Sistem seçimi gereken yanıtın küme mi, kesin kardinalite mi, yaklaşık kardinalite mi olduğunu önce açıklığa kavuşturmalıdır. 26.9 değişiklikleri: https://clickhouse.com/blog/clickhouse-release-26-09.

### 4.5. CTE, WITH, Takma Adlar ve Alt Sorgular

WITH tanımları adlandırılmış ifadeler ve alt sorguların tekrar kullanımını sağlar; CTE'nin mutlaka fiziksel olarak tek kez çalıştığı varsayılamaz. Alias scope ve resolver davranışları SQL lehçesine bağlıdır. Çalışma planındaki tekrarlar EXPLAIN ile doğrulanır.

CTE isimlendirilmiş bir sorgu ifadesidir; her kullanımda mutlaka bir defa hesaplanıp tekrar kullanılan materialized sonuç anlamına gelmez. Subquery kapsamları, alias çözümleme ve scalar expression davranışı özellikle karmaşık `WITH` ifadelerinde dikkatle sınanmalıdır. Aynı yüksek maliyetli ara sorgu birçok yerde kullanılıyorsa alt sorgu düzenleme, materyalleştirilmiş görünüm veya geçici hesaplama seçenekleri plan üzerinden karşılaştırılabilir.

Aynı CTE'nin iki kez referanslanması, bazı yürütme düzenlerinde alttaki sorgunun iki kez değerlendirilmesine yol açabilir. Sorguda değişken örnekleme, `rand()` veya zaman bağımlı ifade bulunuyorsa bu yalnız performans değil sonuç semantiği açısından da önemlidir. Tekrar kullanılan pahalı ara sonuç için geçici tablo ya da fiziksel ön hesaplama tercih edilecekse ara sonucun yaşam süresi ve güncellik gereksinimi tanımlanmalıdır.

ClickHouse 26.3 ile deneysel materialized CTE desteği duyurulmuştur; özelliği bütün kurulumlarda varsayılan kabul etmek doğru değildir. Bir SQL örneğinin uygulamada taşınabilir olabilmesi için gerekli sürüm ve feature flag bilgisi aynı örneğin koşulları arasında belirtilmelidir. Normal CTE, materialized CTE ve kalıcı materyalleştirilmiş görünüm ayrı mekanizmalardır.

Rekürsif bir CTE içindeki yardımcı alt sorgu her iterasyonda yeniden değerlendirildiğinde hem maliyet hem de satırların seçimi değişebilir. ClickHouse 26.10'un rekürsif sorgularda `MATERIALIZED` CTE desteği, yardımcı ilişkinin tek kez hesaplanan sonucunun iterasyonlar boyunca yeniden kullanılmasına imkan verir. Özellikle top-K merkez düğümler gibi sıra eşitliklerinin bulunduğu ara kümelerde materyalleştirme yalnız performans değil tekrarlanabilirlik gereksinimidir. Yardımcı küme K satır ve satır başına w bayt ise bellekte tutmanın alt sınırı kabaca K × w düzeyindedir; yürütme planının gerçek tahsisi ve yeniden kullanımı ayrıca ölçülmelidir. Sıradan `WITH` tanımının her sürümde otomatik olarak bir kez çalışacağını varsaymak doğru değildir. [41]

### 4.6. SQL Standardı ve ClickHouse Sözdizimi Farkları

ClickHouse SQL, ANSI SQL'in tüm davranışlarını otomatik olarak aynı biçimde uygulamaz. JOIN null davranışı, fonksiyon adları, aggregate-state türleri, tarih fonksiyonları ve söz dizimindeki genişletmeler belgelerden doğrulanır. Sorgu taşınabilirliği yalnız parser kabulüyle ölçülmez.

ClickHouse'un SQL arabirimi geniştir fakat SQL:2016 ya da sonraki standartların bütün sözdizimi ve işlem garantilerini eksiksiz uyguladığını varsaymak doğru değildir. `Nullable`, pencere fonksiyonları, `JOIN` sonucu ve NULL sıralaması gibi ayrıntılar farklı motorlarda değişebilir. Oracle ya da PostgreSQL'den taşınan analitik sorgularda yalnız sözdizimi dönüşümü değil aggregate NULL semantiği, ondalık sayı taşması ve zaman dilimi davranışı da test edilmelidir.

ClickHouse'ta tamsayılar arasında `/` işlemi geleneksel olarak kayan noktalı sonuç üretebilir; PostgreSQL gibi bazı motorlar tamsayı bölümünde farklı sonuç verir. 26.10 ile sunulan `sql_compatible_division_for_integers` ayarı, açıkça etkinleştirildiğinde tamsayı bölmesinin sıfıra doğru kırpılmasını sağlar. Örneğin `7 / 2` için 3, `-7 / 2` için −3 sonucu bu uyumluluk kipinde beklenir; ondalıklı operand için farklı semantik geçerlidir. Ayar tabloların saklama biçimini değil ifadenin değerlendirilmesini etkiler. Oracle/PostgreSQL kaynaklı bir raporda bölüm sonucunu daha sonra `CAST` ile dönüştürmek, hesaplama öncesindeki yuvarlama veya sıfıra bölme davranışının eşdeğer olmasını garanti etmez. [41]

## Ünite 5: Veri Ekleme ve Toplu Veri Alımı

ClickHouse eklemelerinde parti boyutu fiziksel parça sayısını etkiler. Çok küçük partiler, aynı veri hacminde daha fazla üstveri ve arka plan birleştirme işi oluşturur.

![Toplu ekleme ve küçük parça maliyeti animasyonu](https://alikoker.com.tr/svg/bulk-insert-part-amplification.svg "Toplu ekleme ve parça maliyeti")


ClickHouse yüksek hacimli INSERT bloklarıyla çalışmak üzere tasarlanmıştır. Tek satırlık veya aşırı küçük parti kullanımı veri parçası oluşturma ve birleşme maliyetini büyütür. Asynchronous inserts istemci tarafında toplu birleştirme ihtiyacını azaltabilir; ancak kabul, disk flush ve tekrar deneme semantiği ayarlarla belirlenir. Akış sistemlerinin en az bir kez teslimi, ClickHouse'un otomatik iş kimliği tekilleştirmesiyle aynı şey değildir.

Aşırı küçük INSERT paketi yüksek işlem hacmi beklentisinde görünmeyen bir sabit maliyeti büyütür: yeni veri parçası oluşturma, üstveri, dosya descriptor ve birleştirme kuyruğu işi. Parti gecikmesini düşürmek için her olayın ayrı gönderilmesi kısa süreli testte düşük gecikme yaratabilir; uzun süreli yükte veri parçası birikimi nedeniyle sorgu performansı bozulabilir. Asynchronous insert sunucuda birleştirmeye yardımcı olur fakat iş uygulamasının onay ve yeniden deneme semantiği halen sınanmalıdır. Kafka tüketiminde offset ve hedef insert'in aynı işlem altında olmaması tam olarak bir kez teslim iddiasını zayıflatır. Kaynak olay kimliği, hedefte idempotent model ve yeniden oynatma testi bu sınırı yönetmenin yollarıdır. CSV/JSON/Parquet format değişiminde şema çıkarımı yerine mümkün olduğunda ilan edilmiş tip sözleşmesi kullanılmalıdır.

### 5.1. Toplu INSERT, Parti Boyutu ve Veri Parçası Maliyeti

Toplu yüklemeler tek INSERT başına yeterli sayıda satır ve makul byte tutmalıdır; çok büyük parti ise bellek sıçraması ve istemci zaman aşımına neden olabilir. En iyi boyut satır genişliği, ağ ve insert concurrency ile ölçülür. Veri parçası sayısı ve birleştirme kuyruğu hedef metriklerdir.

ClickHouse'ta toplu INSERT küçük veri parçası oluşumunu azaltarak depolama motorunun yazma verimliliğini iyileştirebilir. Ancak çok büyük parti tek istek başına ağ, bellek ve yeniden deneme maliyetini artırır. Üretimde ideal parti boyutu satır sayısı kadar sıkıştırılmış bayt, bölüm dağılımı ve sürekli yazma hızına bağlıdır. Her partinin çok sayıda bölüme dağılması beklenenden fazla veri parçası üretebilir. Parti deneyi `system.parts` büyümesi ve sorgu gecikmesiyle birlikte değerlendirilir.

### 5.2. CSV, JSONEachRow, Parquet, Arrow ve Framing

JSONEachRow satır bazlı JSON nesneleri, Parquet kolonsal ikili veri, Arrow sütun tipi aktarım biçimi sağlar. CSV quoting, delimiter ve tip dönüşümü bakımından kırılgandır. Format framing ve bozuk satırda kısmi yükleme davranışı açıkça test edilir.

`JSONEachRow` satır başına bir JSON nesnesi, Parquet ve Arrow ise sütun yönelimli şema/aktarım olanakları sunar. CSV metin olarak basittir fakat ayraç, quoting ve numeric dönüşüm kurallarına duyarlıdır. Arrow veri aktarımında sıfır-kopya olanakları olsa bile sunucu ve istemci arasında ağ aktarımı ortadan kalkmaz. Biçim seçimi yalnız dosya boyutu değil şema kesinliği, decode CPU, kolon budaması ve satır hatalarının raporlanmasıyla belirlenmelidir.

### 5.3. Şema İnference ve Veri Formatı Doğrulama

Şema çıkarımı örneklenen kayıtların kapsamıyla sınırlıdır. İlk satırlarda NULL görünen tarih sütununun String olarak tahmin edilmesi ileride karşılaştırma semantiğini bozabilir. Üretim hattında versiyonlu şema, uyumluluk testi ve reddedilen kayıtların denetimi gerekir.

CSV başlık satırı, kolon sırası, escaping ve boş değer davranışı kaynaklar arasında değişebilir. JSONEachRow'da eksik alan ile açık `null` aynı anlamda değildir; hedef veri tipinin `Nullable` olup olmadığı önemlidir. Parquet'in sütun tipleri ve ClickHouse `Decimal`/`DateTime64` tipleri arasında precision ve saat dilimi dönüşümleri kontrol edilmelidir. Şema inference, birkaç örneğe göre seçilen tipin gelecekteki uç değerleri karşılayacağını garanti etmez; kritik iş yükünde açık şema tercih edilir.

### 5.4. Eşzamanlı ve Asenkron Veri Ekleme

Senkron INSERT işlemin sunucu cevabını bekler; async INSERT kuyruklayıp uyarlanmış flush politikasıyla birden çok küçük veriyi birleştirebilir. `wait_for_async_insert` sonucu istemciye hangi aşamada onay verildiğini etkiler. Ack semantiği iş uygulamasının teslim garantisiyle eşleştirilmelidir.

İstemcinin küçük INSERT'lerini sunucuda toplu yazımla karşılamak için sorgu düzeyi ayarı:

```sql
SET async_insert = 1;
SET wait_for_async_insert = 1;
```

Asenkron kabul ile başarı cevabının hangi aşamada üretildiği bu ayarlardan etkilenir; uygulama timeout/yeniden deneme davranışı yeniden değerlendirilmelidir.

Asynchronous insert, istemci çağrılarıyla oluşan çok küçük veri bloklarını sunucu tarafında biriktirerek daha büyük yazma veri parçalarını üretmeye yardımcı olur. Ancak istemcinin başarı cevabını alması ile verinin kalıcı olarak yazılması arasındaki garanti `wait_for_async_insert` ve diğer ayarlara bağlıdır. Beklemesiz onay, henüz disk üzerinde güvenceye alınmamış veriyi başarılı kabul ettirebilir. Kritik veri hatlarında güvenilir onay sözleşmesi net tanımlanmalı; uygulamanın yeniden deneme ve duplicate politikası sunucu yapılandırmasıyla uyumlu olmalıdır.

İstemci tarafında parti biriktirmek ağ ve istek başlatma maliyetini azaltırken uçtan uca görünürlük gecikmesini artırabilir. Ortalama parti dolum süresi yaklaşık `B/λ` ile modellenebilir (`B`: olay sayısı, `λ`: olay/saniye geliş hızı); düzensiz gelişler ve timeout ile oluşturulan kısmi batch'ler bu hesabı değiştirir. Tasarım, saniyedeki veri parçası sayısı, median/p99 veri alımı lag, burst yükündeki bekleme süresi ve yeniden başlatma sırasında veri kaybı senaryoları üzerinden karşılaştırılır.



ClickHouse 26.3 LTS ile asenkron INSERT davranışı varsayılan olarak etkinleştirilmiştir. Bu sürümde sık gelen küçük INSERT'ler sunucu tamponunda birleştirilerek veri parçası oluşturma baskısı azaltılabilir; `wait_for_async_insert`, tampon boşaltma sınırları ve deduplikasyon ayarları istemcinin ne zaman başarılı yanıt alacağını etkiler. Bir istemcinin kuyruğa alınma onayı ile verinin sorgulanabilir olacak biçimde diske yazılmasının aynı olay olup olmadığı açıkça tanımlanmalıdır. Uygulama yeniden denemesi bu onay sınırıyla uyumlu kurgulanmazsa iki farklı hata modu oluşur: henüz görünür olmayan veriyi başarılı kabul etmek veya zaten yazılmış bloğu yeniden göndermek.

Asenkron varsayılanının öncesindeki ve sonrasındaki sürümler aynı INSERT benchmark'ıyla karşılaştırılırken `async_insert` ayarının gerçek değerinin raporlanması zorunludur. İş yükü altında `system.asynchronous_insert_log`, veri parçası sayısı ve görünür olma gecikmesi birlikte incelenebilir. Kaynak: https://clickhouse.com/blog/clickhouse-release-26-03

26.3 LTS ile asenkron INSERT'in varsayılan olması, istemci tarafından sunucuya gönderilen her kaydın anında okunabilir hale geldiği anlamına gelmez. Sunucu önce uyumlu eklemeleri tamponlayabilir; saklama part'ına flush tamamlanmadan sorgular bu veriyi göremez. `wait_for_async_insert=1` modunda istemci yanıtı flush sonrasına bağlanırken `wait_for_async_insert=0` tampon kabulünde dönebilir. İkinci durumda sunucu çökmesi veya flush hatası istemciye daha önce verilmiş başarı yanıtıyla çelişen veri kaybına neden olabilir.

Aynı tabloya saniyede 100 küçük INSERT gönderilmesi ile 100 kayıtlık tek bir istemci partiyi gönderilmesi aynı sayıda veri parçası oluşturmak zorunda değildir. Asenkron tamponlama, yükü birleştirmenin bir yoludur; akıştaki başarısız kayıtları sessizce yok sayma mekanizması değildir. Üretim veri hattında ACK sınırı, replay ve hataların ayrıştırılması birlikte tanımlanır. Kaynak: https://clickhouse.com/blog/clickhouse-release-26-03.

### 5.5. Eklemede Tekilleştirme ve Yinelenen İşlemlerin Güvenliği

Dedup token veya insert block identity aynı bloğun yeniden gönderiminde tekrar üretimini önlemeye yardımcı olabilir; dedup penceresi sınırlıdır. İçeriği biraz değişmiş iki blok aynı olayları taşıyorsa teknik dedup onu iş düzeyinde tekilleştirmeyebilir. Her olayın benzersiz ve kalıcı kimliği varsa doğrulama daha güçlü olur.

İdempotent yeniden deneme için istemcinin aynı mantıksal veri bloğunu aynı deduplication kimliğiyle gönderebilmesi önemlidir. Sunucunun kısa süreli blok tekilleştirme penceresi sonsuz geçmiş için global benzersizlik garantisi değildir. Yeniden denenen partinin sıra, biçim veya içerik farkı blok kimliğini değiştirebilir. Kaynak olay kimliğini saklamak uzun dönem veri doğrulaması için ek dayanak sağlar. Kafka tüketiminde offset yeniden oynatımı ve ClickHouse INSERT onayı arasındaki boşluklar sınanmalıdır.

### 5.6. Akış ve Toplu İşleme ile Veri Alım Kapasitesi

Tarihsel geçmiş veri yüklemesi büyük batch'lerle, canlı akış düşük gecikmeli küçük batch'lerle gelebilir. İki yolun aynı olayları çifte yazmaması için olay kimliği, zaman aralığı ve kesim noktası tanımlanır. Kaynak yükünün arttığı saatlerde backpressure ve kapasite sınırları önemlidir.

Parti hacmi büyüdükçe INSERT başına üstveri ve veri parçası oluşturma maliyeti azalabilir; ancak bellek ihtiyacı, tek istek gecikmesi ve başarısız partinin yeniden gönderim boyutu artar. Akışla gelen veriyi kısa pencerelerde birleştiren micro-parti yaklaşımı denge kurar. Yük altında insert queue, background birleştirme queue ve analitik sorgu gecikmesi birlikte izlenir. Kaynağın sınırsız hızla veri ürettiği durumda geri basınç veya kalıcı ara kuyruk olmadan kayıpsız veri alımı garanti edilemez.

ClickHouse 26.8'de eklenen `run_query_in_background` ayarı, desteklenen uzun süren sorguların istemci bağlantısı sona erdikten sonra sunucuda yürütülmesini sağlar. İstemciye erken `Ok` dönmesi, veri aktarımının tamamlandığı veya hedef kaydın kalıcılaştırıldığı anlamına gelmez. Çalışan işlemin `query_id` değeri `system.processes` üzerinden, tamamlanma veya hata sonucu ise sorgu günlüğünden kontrol edilir. Bu model, asenkron INSERT tamponunun flush edilmesi, Kafka offset onayı ve materyalleştirilmiş görünüm güncellenmesiyle aynı mekanizma değildir. Arka plan işinin tamamlanmasından önce yeniden başlatılması, idempotency sözleşmesi yoksa mükerrer üretime yol açabilir. İş kimliği, giriş kesiti, hedef sayım ve tamamlanma durumu ayrı kaydedilmelidir. [46]

## Ünite 6: OLAP Kuramı ve Çok Boyutlu Veri Analizi

OLAP işlemleri aynı veriyi farklı ayrıntı düzeylerinde okur. Roll-up, drill-down ve slice/dice hareketleri boyut hiyerarşilerinin sorgu üzerindeki etkisini gösterir.

![OLAP roll-up drill-down animasyonu](https://alikoker.com.tr/svg/olap-cube-rollup-drilldown.svg "OLAP roll-up ve drill-down")


OLAP cebiri, ilişkisel bir veri kümesinin belirli boyutlar altında özetlenmesini biçimselleştirir. Ölçü alanları üzerinde SUM, COUNT, MIN, MAX veya yaklaşık kardinalite hesapları uygulanırken boyutlar sorgu sonuçlarının ayrıştırılma eksenlerini belirler. Aynı veri bir gün, ay ve yıl ayrıntı düzeyinde incelenebilir; fakat bu sonuçların birbirinden türetilebilirliği seçilen ölçünün toplamsallığına bağlıdır. ClickHouse GROUP BY, ROLLUP, CUBE ve grouping sets ile bu işlemleri SQL üzerinden yürütür; yoğun sorgulanan kesitler için agregasyon durumları ayrıca depolanabilir.

Bir olgunun boyutları servis, ülke, zaman ve olay sınıfı olduğunda tam 4-boyutlu küp 16 gruplama kombinasyonuna sahiptir. Fakat her kombinasyonun iş açısından anlamlı olduğu varsayılamaz: servis–ülke günlük dağılımı raporlanırken ülkesiz servis bazlı toplam farklı bir karar için kullanılır. Ayrıntılı bir ölçünün toplamsallığı, zaman boyunca hesaplanan kullanıcı sayısında kaybolabilir. İki saatlik dilimde aynı kullanıcı göründüğünde bağımsız `uniqExact` sonuçları toplandığında mükerrer sayım doğar. Doğru sonuç kullanıcı kimliklerinin birleşimi üzerinden veya birleştirilebilir benzersiz öğe durumlarıyla üretilir. Bu nedenle agregasyon operatörleri yalnız performans aracı değil veri semantiğinin de parçasıdır. KPI tanımı, ölçü birimi, eksik değer semantiği ve geç gelen veriye ilişkin sonradan düzeltme politikasıyla tamamlanmalıdır.

### 6.1. Olgu, Ölçü, Boyut ve Boyut Hiyerarşileri

Olgu tablosunun her satırı bir olayı veya belirli taneciklikteki ölçümü temsil eder. Zaman, kaynak, servis ve bölge boyutları GROUP BY anahtarları olabilir. Satırın tanecikliği tanımlanmadığında COUNT(*) olay sayısını mı, örnek sayısını mı yoksa sürüm sayısını mı verdiği belirsiz kalır.

Bir olgu tablosunun tane düzeyi (grain), tek satırın neyi temsil ettiğine ilişkin doğruluk sözleşmesidir. Örneğin bir satırın "tek bağlantı denemesi" olması ile "bir dakikalık bağlantı özeti" olması aynı `COUNT()` sonucunu farklı anlamlara taşır. Ölçüler toplamsal olsun veya olmasın birim ve ölçüm aralığıyla tanımlanmalıdır. Boyut hiyerarşisinde gün → ay → yıl dönüşümü tek zaman dilimine göre yapılmalıdır; farklı yerel saat dilimleri aynı UTC olayını farklı takvim günlerine taşıyabilir.

### 6.2. Toplamsal, Yarı Toplamsal ve Toplamsal Olmayan Ölçüler

Toplam olay adedi tüm boyutlarda toplanabilir; benzersiz kullanıcı sayısının bölüm sayılarından toplanması aynı kullanıcı birden fazla bölümde göründüğünde yanlıştır. Ortalama da doğrudan ortalamaların ortalamasıyla hesaplanamaz; toplam ve adet korunmalıdır. Bu nedenle state tabanlı agregasyon tasarımı ölçünün cebirsel özelliğine dayanır.

Ölçülerin toplamsallığı zamana ve diğer boyutlara göre ayrı tanımlanır. Olay sayısı çoğu boyutta toplanabilir: `count(A ∪ B) = count(A) + count(B)` eşitliği ancak A ile B'nin ayrık olması halinde doğrudur. Gün sonundaki hesap bakiyesi iki ardışık gün boyunca toplanamaz; belirli bir anda birden fazla hesap üzerinde toplanabilir. Bu ölçüler yarı toplamsaldır. Ortalama, oran, yüzde ve benzersiz kullanıcı sayısı ise kendi sonuç değerleri üzerinden genel olarak toplanamaz.

Ayrık iki grubun ortalamalarını `μ₁` ve `μ₂`, gözlem sayılarını `n₁` ve `n₂` olarak gösterirsek birleşik ortalama `(n₁μ₁+n₂μ₂)/(n₁+n₂)` biçimindedir. Yalnız ortalama değerini saklayan bir materyalleştirilmiş görünüm, sonradan doğru birleşim için yeterli bilgiye sahip olmayabilir. ClickHouse'ta `avgState`, `uniqState` gibi birleştirilebilir durumlar, doğru biçimde seçilmiş `AggregatingMergeTree` ve sorgu anındaki `…Merge` fonksiyonlarıyla bu sorunu giderir. Approximate distinct durumlarının birleşmesi matematiksel olarak tahmini bir sonuç üretir; `uniqExact` gibi kesin algoritmalar daha yüksek bellek tüketebilir.

Oran için pay ve payda ayrı tutulmalıdır. Bölgelere göre hata oranlarının aritmetik ortalaması, bölge trafik hacimleri farklıysa genel hata oranı değildir. Örneğin 10 istekte 1 hata ve 1000 istekte 10 hata varsa oranların ortalaması %5,5 iken gerçek birleşik hata oranı `11/1010 ≈ %1,09` olur. Veri ambarı ölçü tanımı, saklanacak ara durumların seçimini doğrudan belirler.

Toplamsal ölçü `SUM` ile ayrık gruplardan tekrar üretilebilir. Stok bakiyesi zaman boyunca toplandığında anlamını kaybedebildiğinden yarı toplamsaldır. Ortalama, oran ve benzersiz kullanıcı sayısı genellikle yalnız nihai skaler değerlerin toplamıyla yeniden hesaplanamaz. Ortalama için (toplam, kayıt sayısı), varyans için yeterli sayısal durum, yaklaşık benzersiz sayım için birleşebilir eskiz (sketch) tutulması gerekir. Örneğin bölümlerin ayrı ayrı ortalamasını ağırlıksız almak, bölüm büyüklükleri farklıysa bütünün ortalamasını vermez.

Ölçülerin toplanabilirliği sorgulanan boyutla ilişkilidir. Günlük satış tutarı tarihler üzerinden toplanabilirken gün sonu bakiye aynı hesabın birbirini izleyen günlerinde toplandığında anlamlı toplam oluşturmaz. Bakiye, hesap boyutu üzerinden toplanabilir fakat zaman boyutunda genellikle son gözlemin seçilmesini gerektirir; bu yüzden yarı toplamsaldır. Oran ve yüzdeler genellikle doğrudan toplanmaz; pay ve payda ayrı saklanıp nihai grupta yeniden hesaplanır. `avg(avg_latency)` genel ortalamayı ancak gruplar eşit ağırlıklıysa verir. Doğru birleşim `Σ(duration_sum)/Σ(request_count)` biçimindedir.

Bu ayrım ClickHouse'un kısmi agregasyon stratejisine de yansır. `sumState`, `countState` ve `avgState` birleştirilebilir durumlar üretir; `avgMerge` veya uygun finalization işlemi birleşik istatistiği hesaplar. Medyan genel olarak alt grup medyanlarından hesaplanamaz. Yaklaşık quantile algoritmasının durumu korunabilir; yalnız son sayı saklanırsa sonraki gruplama düzeylerinde bilgi kaybı yaşanır.

Toplamsal ölçülerde agregasyon işlemi ayrık veri bölümleri üzerinde dağıtılabilir: SUM(A ∪ B) = SUM(A) + SUM(B). Sayım da aynı özelliği taşır; AVG ise tek bir sayı olarak saklandığında bu özelliğe sahip değildir. İki grubun ortalamaları μ₁ = 10, μ₂ = 40 ve örnek sayıları n₁ = 9, n₂ = 1 ise birleşik ortalama (n₁μ₁ + n₂μ₂)/(n₁ + n₂) = 13 olur; (μ₁ + μ₂)/2 = 25 yanlıştır. Ön hesaplama tablosu toplamı ve örnek sayısını veya bunların birleşebilir agregasyon durumunu saklamalıdır.

Ayrık sayımda `uniqExact` ile tam sonuç, `uniq` ailesindeki yaklaşık yöntemlerle bellek–hata değiş tokuşu elde edilir. Önceden üretilmiş iki ayrı tekil sayıyı toplamak, kümeler kesişiyorsa mükerrer sayım üretir: |A ∪ B| = |A| + |B| − |A ∩ B|. Dağıtık distinct hesabında kısmi sonuçların birleşebilir durumları bu nedenle önemlidir. Birleştirilebilir olmayan ölçüler için ham kayıtların veya yeterli istatistiksel özetlerin korunması gerekir.

### 6.3. OLAP İşlemleri: Üst Düzey Toplulaştırma, Ayrıntıya İnme, Dilimleme ve Eksen Dönüşümü

Roll-up detaylı boyut düzeyini üst hiyerarşiye taşır; drill-down daha ayrıntılı kırılıma iner. Slice tek boyut değerine kısıtlama, dice birden fazla boyut üzerinde alt küme seçimi, pivot ise sonuç eksenlerinin gösterimini değiştirir. Bu işlemler fiziksel indeks türü değil analitik dönüşümlerdir.

`roll-up` daha kaba ayrıntı düzeyine geçiş, `drill-down` daha ince ayrıntı düzeyine geçiştir; bu iki işlem ancak her alt hücrenin doğru üst hücreye eşlendiği durumda karşılıklı tutarlı sonuç verir. `slice` bir boyutta değer sabitlerken `dice` birden fazla boyut üzerinde alt küme seçer. `pivot`, ölçüm sonucunun satır/sütun sunumunu değiştirir; agregasyon semantiğiyle aynı işlem değildir. İlişkisel tabloda kaydedilen coğrafi birim değişiklikleri ve boyut üyeliği tarihçesi, roll-up işlemlerinde çift sayımı engellemek üzere ayrıca tanımlanmalıdır.

### 6.4. CUBE, ROLLUP, GROUPING SETS ve İlişkisel Cebir

`GROUP BY` tek bir boyut kümesine, `ROLLUP` seçilmiş hiyerarşinin ön eklerine, `CUBE` ise boyutların bütün alt kümelerine ilişkin agregasyonları hesaplar. `GROUPING SETS` yalnız istenen alt kümelerin seçilmesini sağlar. k bağımsız boyut için tam küp en çok 2ᵏ gruplama kümesi içerir; bunun sonuç satırı sayısı, her kümedeki farklı anahtar birleşimlerinin toplamına bağlıdır.

İki boyutlu bir servis–gün örneğinde hem ayrıntı satırları hem servis toplamları hem de genel toplam tek sorguda hesaplanabilir:

```sql
SELECT
    service_id,
    toDate(event_time) AS event_day,
    GROUPING(service_id, event_day) AS grouping_id,
    count() AS event_count
FROM events
WHERE event_time >= toDateTime64('2026-10-01 00:00:00', 3, 'UTC')
  AND event_time < toDateTime64('2026-11-01 00:00:00', 3, 'UTC')
GROUP BY ROLLUP (service_id, event_day)
ORDER BY grouping_id, service_id, event_day;
```

`GROUPING` işlevi anahtarın gerçek veri değeri olarak mı, yoksa ara toplam üretimi sırasında mı temsil edildiğini ayırt eder. ClickHouse'ta ara toplamlarda eksik anahtarlar varsayılan olarak ilgili veri tipinin öntanımlı değeriyle gösterilebilir; dolayısıyla `0` veya boş tarih tek başına güvenilir toplam göstergesi değildir. NULL kullanımı `group_by_use_nulls` ayarına bağlıdır. Örneğin sıfır kodlu geçerli bir servis varsa, yalnız görünen anahtar değerine bakılarak servis toplamı ile servis kimliği karıştırılabilir.

`ROLLUP(a,b,c)` sırasıyla (a,b,c), (a,b), (a) ve () kümelerini oluşturur; `CUBE` sekiz alt kümeyi kapsar. Bir raporda 12 boyut için 4096 gruplama kümesini otomatik üretmek, yalnız belirli hiyerarşiler istendiğinde gereksiz hesaplama yaratır. `GROUPING SETS ((service_id, event_day), (service_id), ())` gibi sınırlı seçim, talep edilmeyen boyut birleşimlerini dışlar. Ön hesaplamaya karar verilirken veri tazeliği, grupların kardinalitesi ve saklama maliyeti birlikte değerlendirilir. [1, 2]

### 6.5. ROLAP, MOLAP, HOLAP ve Küp Modelleri

ROLAP boyut analizini ilişkisel tablolar ve SQL ile gerçekleştirir; MOLAP önceden hesaplanmış çok boyutlu yapılara dayanır; HOLAP bu yaklaşımları birleştirir. ClickHouse klasik çok boyutlu küp dosyası zorunluluğu olmadan sütun tablosundan sorgu anında özet çıkarabilir; materyalleştirilmiş görünüm ile ön hesaplanmış özetler de oluşturabilir.

ROLAP'ta küp hücreleri gerektiğinde SQL sorgusuyla hesaplanabilir; MOLAP'ta hücrelerin tümünün önceden tutulması zorunlu değildir, seçili özetler saklanabilir. HOLAP bu iki strateji arasında tanımlanan erişim ve hesaplama ayrımını ifade eder. Boyut sayısı k olduğunda teorik gruplama kümesi sayısı 2ᵏ olabilir; gerçek depolama yükü, her kümenin farklı anahtar kombinasyonu sayısına bağlıdır. ClickHouse üzerinde ham olayları koruyup sık sorgulanan boyut birleşimleri için `AggregatingMergeTree` tablosu tutmak, klasik küp malzemeleştirmenin sorgu odaklı bir karşılığıdır.

OLAP ve veri ambarı literatürünün bu ayrımı, Chaudhuri ve Dayal (1997) tarafından sistematik olarak açıklanmıştır; veri küpü işlemlerinin ilişkisel cebirle ilişkisi Gray ve diğerleri (1997) çalışmasında biçimselleştirilmiştir.

### 6.6. Veri Küplerinin Materyalleştirilmesi ve Ön Hesaplama Maliyeti

Ön hesaplama sorgu süresini düşürürken ek depolama, INSERT sırasında CPU ve geç gelen olayların düzeltilmesi maliyeti doğurur. Bütün boyut birleşimlerini tutmak üstel biçimde büyüyebilir. Sık kullanılan sorgu aileleri seçilmeli; kaynak olgu tablosu gerektiğinde yeniden hesaplama için korunmalıdır.

Ön hesaplama kararında sorgu maliyeti Q, özet güncelleme maliyeti U, özet depolama maliyeti S ve sorgu sıklığı λ birlikte düşünülür. Belirli bir zaman ufku H için toplam maliyet yaklaşık λ × H × Q + H × U + S olarak modellenebilir. Özet eklemek sorgu maliyetini azaltırken yazma yolunu ve hata sonrası yeniden üretim işini büyütür. Olayların güncellenmesi veya geç gelmesi durumunda özetin yeniden hesaplanma stratejisi belirlenmeden hızlandırma tasarımı tamamlanmış sayılmaz.

## Ünite 7: Analitik Veri Modelleme ve Veri Ambarları

Veri ambarı tasarımında temel karar tablonun fiziksel adı değil, tek bir satırın hangi olay veya durumu temsil ettiğidir. Olay-zamanı, sisteme alınma zamanı ve işleme zamanı ayrı sütunlarda tutulduğunda geç gelen veri ile işlem gecikmesi ayrıştırılabilir. OLTP şemasının normalleştirilmiş yapısını birebir analitik tabloya taşımak çok sayıda JOIN ve dağınık okuma üretebilir; ancak kontrolsüz denormalizasyon da veri çoğaltma ve tarihsel boyut yanlışlığı doğurur.

Bir ağ bağlantısı olayının başlangıçta oluşup oturum sonunda süre bilgisinin güncellenmesi, tek başına append-only olay modeliyle aynı değildir. İki ayrı olayı tek bir satır durumuna indirgemek istenirse olay kimliği ve sürüm kuralı gerekir; aksi halde bağlantı süresi toplamında aynı oturum iki kez sayılabilir. Olgu tablosu yalnız gerçekleşmiş olayları içeriyorsa düzeltmeler için ayrı compensating event veya version history kullanılabilir. Boyutların güncel değerleriyle yapılan denormalizasyon geçmiş sınıflandırmayı değiştirebilir: geçmişte A grubuna ait olan servisin sonradan B grubuna taşınması raporu geriye dönük değiştirir. Tarihsel doğruluk isteniyorsa boyut geçerlilik aralıkları ve değişiklik zamanı korunur. OLAP sorgusundaki `toDate(event_time)` ifadesinin UTC mi yerel takvim günü mü hesapladığı rapor tanımının bir parçası olmalıdır.

### 7.1. Olgu Tanecikliği ve Yapay Anahtar Stratejileri

Grain, olgu tablosunda tek satırın hangi olaya karşılık geldiğinin sözleşmesidir. Olay kimliği üretmeyen kaynaklarda aynı değerleri taşıyan iki gerçek olayın yanlışlıkla tekilleştirilmesi tehlikelidir. Surrogate key boyut geçmişini ayırmaya yardımcı olur; anahtarın benzersizliği kaynakta ve CDC hattında doğrulanmalıdır.

Birincil olgu tanesi belirlenmeden surrogate key oluşturulması mükerrer kayıtları ortadan kaldırmaz. Kaynaktaki aynı mantıksal olay iki defa teslim edilebiliyorsa hedefte doğal olay kimliği, kaynak işlem konumu veya deterministik birleşik anahtar kullanılabilir. ClickHouse MergeTree birincil anahtarı, geleneksel ilişkisel veritabanlarındaki `UNIQUE` kısıtı gibi eşsizliği kendiliğinden zorlamaz. Olgu tablosunun olay-kimliği semantiği ile `ORDER BY` sıralama semantiğinin ayrılması, deduplication ve sorgu optimizasyonunu farklı amaçlarla tasarlamayı sağlar.

### 7.2. Yıldız ve Kar Tanesi Şemaları

Yıldız şema olgu tablosunu doğrudan boyut tablolarına bağlar. Kar tanesi şema boyutların kendi içinde normalleştirildiği düzeni temsil eder. ClickHouse'ta JOIN maliyeti önemliyse sık kullanılan ve küçük boyutlar sözlük veya yazım anında zenginleştirme ile ele alınabilir; tarihsel boyut değişimi gerekiyorsa aynı kısayol doğruluğu bozabilir.

Yıldız şema, olgu tablosunun boyutlarla doğrudan bağlandığı, boyutların görece denormalize tutulduğu düzeni tanımlar. Snowflake şemasında boyut hiyerarşileri birden çok ilişkili tabloya ayrılabilir. ClickHouse'ta yaygın sorgularda JOIN maliyetini azaltmak için boyutların olay satırına taşınması yararlı olabilir; bunun bedeli boyut güncellemesi, depolama tekrarı ve tarihsel yorumlama zorluğudur. Özellikle geçmiş olayların o tarihteki boyut niteliğiyle mi yoksa bugünkü tanımla mı raporlanacağı açık bir model kararıdır.

### 7.3. Denormalizasyon ve Boyut Tabloları

Denormalizasyon sorgu zamanında JOIN azaltırken tekrar eden açıklama alanları için depolama ve güncelleme maliyeti doğurur. ClickHouse'un sıkıştırması tekrarların bir kısmını düşük maliyetle tutabilir; fakat bir kategori adının geçmişte ne olduğu analitik bakımından önemliyse değişiklik zamanları ayrıca modellenir.

Önceden birleştirme (denormalizasyon) kararı, küçük bir boyutun her olay üzerinde kaç kez kopyalanacağını ve güncellemelerin nasıl yansıtılacağını birlikte hesaba katar. Boyut değeri olay anında sabitse kayıt sırasında eklenmesi basit ve hızlıdır. Güncellenen müşteri sınıflandırması gibi alanlarda eski olayların yeni sınıfla gösterilmesi gerekiyorsa sözlük veya JOIN, ham olgunun yeniden yazılmasına göre daha uygun olabilir. Yalnız JOIN hızından hareketle tüm boyutları olgu tablosuna kopyalamak veri soy ağacı ve bakım maliyetini büyütür.

### 7.4. SCD Type 1/2/3 ve Tarihsel Doğruluk

SCD Type 1 önceki boyut değerinin üzerine yazar; Type 2 geçerlilik aralıklarıyla tarihsel sürümler saklar; Type 3 sınırlı sayıda önceki değer alanı tutar. Eski olayın yeni isim altında mı, o tarihteki isim altında mı raporlanacağı açıkça belirlenmelidir. ASOF veya zaman-aralıklı JOIN gerekebilir.

SCD Type 1 boyut değişikliğinde eski alan değerinin üzerine yazılır; geçmiş analitik sonuçlar güncel boyut nitelikleriyle yorumlanır. Type 2 her değişiklik için geçerlilik aralığı tanımlayarak tarihi korur. `valid_from ≤ event_time < valid_to` koşulu, olayın gerçekleştiği anda geçerli niteliği belirler. `valid_to` için açık uçlu kayıt kullanılırken null veya en büyük zaman değeri sözleşmesi bütün sistemlerde aynı olmalıdır. Type 3 sınırlı sayıda geçmiş değeri ayrı sütunlarda tutar ve genel tarihsel çözüm sunmaz.

SCD Type 2 tabloya olay geldiğinde boyut sürümlerinin tarih aralıkları örtüşmemelidir. Boyut kaydının sonradan gelmesi, bir olayın daha önce bilinmeyen sürümle eşleşmesini gerektirebilir. ClickHouse sorgularında zaman aralıklı JOIN veya önceden hesaplanmış boyut zenginleştirmesi kullanılabilir; seçimin maliyeti boyut değişim sıklığı, veri tazeliği ve yeniden işleme hacmiyle belirlenir. Boyut değerini olay tablosuna gömmek sorguyu hızlandırabilir, ancak geçmişin geriye dönük düzeltilmesini pahalılaştırabilir. Denormalizasyon, tarihsel doğruluk kuralından bağımsız bir optimizasyon değildir.

Bir boyut değişikliğinin yalnız `valid_from` zamanına göre çözümlenmesi, geçerlilik başlangıcı ile düzeltmenin sisteme işlendiği zaman farklıysa yeterli değildir. İş zamanının yanında sistemde bilinme zamanını da tutan çift zamansal (bitemporal) model, geçmişte yayımlanan raporun hangi veri sürümüne dayandığını yeniden kurmaya olanak verir. Bu gereksinim yoksa tek geçerlilik aralığı daha az depolama ve daha basit sorgu üretir.

Zaman aralıklı sürüm çözümlemesinde yarı açık aralık kullanılması sınırdaki olayın iki sürüme birden bağlanmasını önler. Örnek: Bir müşteri sınıflandırması 09:00'da A, 11:00'de B olmuşsa 11:00 olayının hangi sürüme bağlanacağı `valid_from` değerinin kapsayıcı olmasına göre kesinleştirilir. Kaynak sonradan 10:30'a etkili düzeltme gönderirse, daha önce A'ya bağlanmış 10:45 olayları da yeniden değerlendirilebilir. Bu değişiklik yalnız boyut satırını güncellemekle çözülmeyebilir; önceden zenginleştirilmiş olgu kayıtları ve özet tabloları da yeniden hesaplanabilir.

Büyük olgu tablolarında tarihsel aralık eşleştirmesinin bellek maliyeti büyüyebileceğinden, boyut sürümlerinin anahtar ve zaman bazında düzenlenmesi ile doğru ASOF/interval JOIN planı kıyaslanır. ASOF, eşleştirilen sürümün daha eski olması koşulunu doğal kurabilir; ancak bir sonraki `valid_to` sınırı veya geçerlilik boşlukları gerektiğinde ek doğrulama şarttır.

Geçerlilik zamanı (valid time), bir olgunun iş alanında hangi zaman aralığı için doğru olduğunu; sistem zamanı (system time) ise kaydın veri sisteminde ne zaman tutulduğunu belirtir. Bir fiyat değişikliği 1 Ekim'den itibaren geçerli olup 3 Ekim'de sisteme girilmişse “1 Ekim'de geçerli olan fiyat” ile “2 Ekim günü sistemin bildiği fiyat” farklı sorgulardır. Tek `updated_at` alanı bu iki soruya güvenilir yanıt veremez.

SCD Type 2 modelinde aynı iş anahtarı için `[valid_from, valid_to)` biçiminde çakışmayan geçerlilik aralıkları tanımlanabilir. Geç gelen değişiklik, araya yeni sürüm yerleştirilmesini ve iki komşu aralığın düzeltilmesini gerektirebilir. MergeTree'nin sıralama anahtarı bu aralıkların mantıksal çakışmazlığını kendiliğinden zorunlu kılmaz; iş kuralı kaynak veri yönetiminde veya doğrulama işinde uygulanır. Geçmiş raporların tekrar üretilebilmesi için geçerlilik zamanı kadar yüklenen sürümün kaynağı da izlenmelidir.

### 7.5. Olay Zamanı, Veri Alım Zamanı ve İşleme Zamanı

Olay zamanı olayın gerçekleştiği an, veri alım zamanı hedefe ulaştığı an, işleme zamanı analitik işleyicinin kaydı ele aldığı andır. Sıralama ve bölüm seçiminde birinin kullanılması diğerlerinin anlamını ortadan kaldırmaz. Gecikmiş paket, yeniden gönderim ve saat farkları zaman pencerelerini farklı etkiler.

Olay zamanı, kaynağın olayı meydana gelmiş saydığı anı; işleme zamanı akış işlemcisinin olay üzerinde çalıştığı anı; alım zamanı hedefin kaydı kabul ettiği anı tanımlar. Bu zamanlar ağ gecikmesi, geç teslim, geri doldurma ve saat kayması nedeniyle farklılaşabilir. `toStartOfHour` gibi zaman penceresi hesapları doğru zaman alanıyla yapılmalıdır. Özellikle veri geriye dönük yüklendiğinde alım zamanına göre bir saatlik sorgu gerçek olay yoğunluğunu değil yükleme işleminin yoğunluğunu gösterir.

### 7.6. Geç Veri, Yeniden İşleme ve Veri Kalitesi

Geç olay, tamamlanmış görünen günlük agregasyonu değiştirebilir. Watermark bir mutlak doğruluk garantisi değil gecikmeye ilişkin bir kabul politikasıdır. Yeniden işleme halinde sonuç tekilleştirme anahtarları, aggregate state düzeni ve hedef tabloya yeniden yükleme sınırları tanımlanmalıdır.

Geç veri politikası kesin kapanmış ve sonradan değişmeyecek dönemlerle yeniden hesaplanabilir dönemleri ayırmalıdır. Örneğin bir günün özetinin gece yarısı kesinleştiğini varsaymak, ertesi sabah gelen olayları dışarıda bırakır. Olay süresi ve kaynak işlem konumu birlikte tutulursa belirli aralıklar tutarlı biçimde tekrar işlenebilir. Veri kalitesi denetimleri yalnız satır sayısına indirgenemez; boş değer oranı, tekillik, zaman aralığı, ölçü toplamı ve çok tablolu ilişki bütünlüğü ayrı doğrulanır.

### 7.7. Veri Ambarı, Lakehouse ve Veri Hattı Mimarileri

Warehouse veri sunumu ve yönetilen şema sorumluluğunu; lakehouse açık dosya biçimleri ve tablo üstveri katmanını öne çıkarır. ClickHouse, S3/Parquet gibi kaynakları doğrudan okuyabilir veya kendi MergeTree düzeninde tutabilir. Harici okumalar ile yerel sıralama/indeks avantajlarının maliyeti ayrı ölçülür.

Veri ambarı, analitik amaçlı kurumsal veri bütünleştirme yaklaşımıdır; lakehouse ise açık dosya biçimleri ve tablo üstveri katmanını birleştiren mimariler için kullanılır. ClickHouse, Parquet gibi sütunlu dosyaları doğrudan okuyabilir; ancak dış dosyadaki üstveri ve işlem garantileri, MergeTree ile aynı kabul edilmemelidir. Bir lakehouse üzerinde dış sorgu katmanı kurulurken dosya sayısı, nesne deposu listeleme maliyeti, şema evrimi ve bölüm keşfi toplam sorgu süresini belirler.

## Ünite 8: Sütun Yönelimli Depolama ve Veri Sıkıştırma

Sütunlu düzenin temel kazancı, sorguda kullanılmayan sütunları hiç okumamaktır. Benzer değerlerin ardışık tutulması ayrıca sıkıştırma oranını yükseltir.

![Sütun budama ve sıkıştırma animasyonu](https://alikoker.com.tr/svg/columnar-pruning-compression.svg "Sütun budama ve sıkıştırma")


Sütun yönelimli depolama, okuma sırasında yalnız gerekli alanları getirmenin yanında aynı tipteki değerlerin birlikte kodlanmasına imkan verir. Sıkıştırma biçimi veri dağılımına bağlı seçilir; sıralı timestamp değerleriyle rastgele UUID sütunlarının entropisi aynı değildir. Bir codec'in daha yüksek sıkıştırma oranı sağladığı gözlense bile toplam sorgu gecikmesindeki değişim çözme CPU'su ve önbellek davranışı olmadan yorumlanamaz.

Sıralama anahtarı üzerinde aynı servise ait olayların yan yana saklanması, `service_id` sütununu tekrar eden kodlara dönüştürerek sıkıştırmayı kolaylaştırabilir. Zaman damgalarının artan sıra içinde olması Delta türü dönüştürmelerin çalışabileceği örüntüyü güçlendirebilir. Ancak aynı düzen yalnız zamana göre sorgularda daha fazla veri okunması anlamına gelebilir. Sıkıştırma ve indeksleme kararı dolayısıyla birbirinden bağımsız değildir. Uygun codec'i seçmeden önce her sütunun gerçek veri dağılımı, sıfır/NULL oranı, tekrar uzunluğu ve güncellenme modeli ölçülmelidir. Büyük String sütununda düşük CPU maliyetli bir codec hızlı tarama için uygun olurken soğuk arşivde depolama fiyatı daha ağır basabilir. Kodlama öncesi tip daraltması bazen codec değiştirmekten daha yüksek tasarruf sağlar fakat değer aralığının doğruluğunu riske atmamalıdır.

### 8.1. Sütun Budama ve Bellek Yerelliği

Sütun pruning, sorguda başvurulmayan sütunların diskten getirilmesini önler. Seçilen sütunun filtre sonucu gereken satırlara kadar geciktirilmesi ayrıca late materyalleştirme olarak adlandırılır. İki mekanizma farklı aşamalarda bayt ve bellek tahsislerini azaltabilir.

Bir sorguda sütunların yalnız küçük bir alt kümesi kullanıldığında sütun pruning doğrudan G/Ç azaltımı sağlar. Ancak `SELECT *` veya gereksiz büyük JSON sütunlarının seçilmesi bu kazanımı ortadan kaldırır. İlgili filtre sütununun erken okunması ve eşleşen satırlar belirlendikten sonra sonuç sütunlarına geçilmesi, filtre etkisinin sadece hesaplama değil veri aktarımı maliyetine de yansımasını sağlar. Bu davranış sorgu planındaki okuma aşamalarından doğrulanabilir.

### 8.2. Sıkıştırma Blokları ve Granüllerin Etkileşimi

MergeTree part'larında granül mantıksal işaretleme ve erişim birimidir; sıkıştırma bloğu ise kodlama ve I/O çevresindeki fiziksel birimdir. Biri diğerine bire bir eşit olmak zorunda değildir. Seçici filtre ve küçük sıkıştırma bloklarının birleşimi, okuma miktarını ve üstveri yükünü etkiler.

Bir granül mantıksal satır grubudur; sıkıştırılmış blok ise fiziksel depolama ve çözme birimidir. Bu iki sınırın birebir çakışması gerekmez. Bir işaret aralığı seçildiğinde fiziksel sıkıştırma bloğının tamamının okunması zorunlu olabileceğinden seçicilik çok yüksek olsa bile sıfır ek okuma elde edilmez. Özellikle küçük noktasal sorgularda fazla sayıda minik veri parçası ve blok açma maliyeti baskınlaşabilir.

### 8.3. LZ4, ZSTD, Delta, DoubleDelta, Gorilla, T64

LZ4 genellikle düşük CPU maliyeti, ZSTD yüksek sıkıştırma oranı hedefler. Delta ardışık farkları; DoubleDelta farkların farklarını kodlar. Gorilla benzeri yaklaşımlar bazı kayan nokta zaman serilerinde bit örüntüsü tekrarından yararlanır. T64 bit genişliğine dayalı temsil sağlar; uygunluk veri örüntüsüyle ölçülür.

Codec seçimi için artan 64-bit timestamp dizisi üzerinde Delta/DoubleDelta etkisi incelenebilir. Örneğin saniyede bir örneklenen zamanlar `1000,1001,1002,1003` biçimindeyse ilk farklar `1,1,1`, ikinci farklar `0,0` değerlerini verir. Sıkıştırılabilirlik farkların daha dar bit genişliğiyle temsil edilebilmesine dayanır. Rastgele veya düzensiz örneklemelerde aynı dönüşüm yarar sağlamayabilir. `ZSTD` seçimi de yalnız ham/sıkıştırılmış byte oranıyla değil saniyede çözülen örnek sayısıyla değerlendirilir.

Kodlama ve sıkıştırma aynı işlem değildir. Delta, DoubleDelta ve T64 gibi codec'ler verinin yapısından yararlanarak temsilini dönüştürür; LZ4 ve ZSTD ise oluşan bayt dizisini sıkıştırır. Dönüşümün ardından kalan artıkların dağılımı, son sıkıştırma oranını belirler. Birden fazla codec'in zincirlenmesi ancak ilgili veri tipinde desteklenen sıra kullanıldığında anlamlıdır. Kodlama seçimi dosya boyutuna ek olarak çözücü işlem hacmini, okunan sütun sayısı ve gerçek sorgu gecikmesiyle değerlendirilir.

Sıkıştırma oranı `C = B_ham/B_sıkıştırılmış` olarak tanımlansın. `C=8`, dosya boyutunun sekizde bire inmesi demektir; “%800 küçüldü” anlamına gelmez. Bir sütunun 8 kat sıkıştırılması bütün tablonun 8 kat küçüldüğünü de göstermez. Örneğin ham tabloda zaman sütunu toplamın %20'sini oluşturuyorsa ve yalnız bu sütunun boyutu 8 kat azalırsa toplam boyut `0,80 + 0,20/8 = 0,825` düzeyine iner. Ham toplam üzerinden kazanım yaklaşık %17,5'tir. Bu ilişki sıkıştırmanın Amdahl yasasına benzer sınırlamasıdır.

ClickHouse'un sıralama düzeni codec verimini etkiler. Ardışık zamanların gruplanması Delta için elverişli olabilirken diğer sorgularda filtre seçiciliği daha önemli olabilir. Veri tipini `Float64`ten `Float32`ye indirmek yalnız yer tasarrufu değildir; ölçüm doğruluğu, yuvarlama ve sonradan yapılan toplamlarda hata birikimi değerlendirilmelidir. Sıkıştırma ile sorgu süresi arasındaki doğru karar, aynı temsil üzerinde soğuk ve sıcak sorgu ölçümleriyle verilir.

ClickHouse 26.10 ile sayısal diziler için deneysel PCO codec desteği tanıtılmıştır. Bu yöntem ile Delta/DoubleDelta ve genel amaçlı sıkıştırma algoritmaları arasındaki seçim, sabit uzunluklu sayısal değerlerin dağılımına göre yapılmalıdır. Kaynağın aynı test kümesi üzerinde bildirdiği sıkıştırma oranları, işaretli tamsayı ve Float64 kolonlarında farklı yönlerde değişmektedir; PCO için her veri tipinde tek bir üstünlük sırası yoktur. Deneysel özellik `enable_pco_codec` ayarına bağlıdır ve kalıcı şemaya uygulanmadan önce sürüm uyumluluğu ile okuma/yazma davranışı doğrulanmalıdır. [41]

Bir codec deneyinde her aday aynı sıralanmış satır dizisini işlemeli; `sum(data_compressed_bytes)` ve `sum(data_uncompressed_bytes)` benzeri depolama ölçülerine ek olarak soğuk/sıcak okuma gecikmesi, saniyede çözülen değer sayısı ve INSERT CPU tüketimi kaydedilmelidir. Sıkıştırma oranı r = Bₕₐₘ / Bₛıₖışmış, net depolama tasarrufu ise 1 − 1/r olarak tanımlanır. Sadece bayt sayısındaki kazanç, sık sık okunan sütunlar için toplam maliyeti belirlemez.

### 8.4. Sözlük Kodlaması ve Tekrar Sayısı Kodlaması

Dictionary encoding tekrar eden değerleri küçük kodlara dönüştürür. RLE uzun eşit-değer dizilerini (değer, tekrar sayısı) biçiminde saklar. Sıralama anahtarının benzer değerleri yakınlaştırması hem RLE olasılığını hem de genel amaçlı sıkıştırma verimini artırabilir.

Run-length encoding ardışık eşit değerleri (değer, tekrar sayısı) olarak temsil eder; sıralamanın benzer değerleri yaklaştırması bu kodlamayı iyileştirebilir. Dictionary encoding farklı değerleri bir sözlükte tutup ana kolonda kısa kodlar kullanır. `LowCardinality(String)` gibi yapıların maliyeti sözlük büyüklüğü, dağılım ve her veri parçasının ayrı sözlük ihtiyacına bağlıdır. Çok yüksek kardinaliteli ve neredeyse tekil değerlerden oluşan alanlarda sözlük yönetim maliyeti kazanımı azaltabilir.

### 8.5. Sıkıştırılabilirlik, Kardinalite ve Veri Dağılımı

Kardinalite benzersiz değer sayısıdır; tek başına sıkıştırma oranını belirlemez. Değer dağılımı, ardışık korelasyon, NULL yoğunluğu ve fiziksel sıra da önemlidir. Sıkıştırma değerlendirmesinde `system.parts_columns` ölçüleri karşılaştırılırken aktif veri parçaları ve test verisinin dağılımı korunmalıdır.

Sıkıştırma oranını yalnız veri tipinin uzunluğu değil tekrar deseni, entropi ve değerlerin fiziksel sırası belirler. Zaman damgalarının monoton ilerlemesi ardışık farkları küçülterek Delta/DoubleDelta kodlamasını elverişli kılabilir; rastgele UUID değerleri aynı derecede sıkıştırılmayabilir. Sıralama anahtarı belirlenirken sorgu seçiciliği ile depolama sıkıştırması farklı hedefler olarak değerlendirilmelidir. Kötü sıralama altında daha güçlü codec seçmek, kaybolan indeks budaması avantajını her zaman telafi etmez.

Veri kodlayıcılarının etkinliği yalnız sütunun istatistiksel dağılımına değil fiziksel satır sırasına da bağlıdır. Sıralanmış bir olay akışında `event_time` ardışık değerler ürettiğinden Delta/DoubleDelta dönüşümleri küçük farklar sağlar; aynı sütun rastgele yeniden sıralanırsa farkların entropisi artar. Düşük kardinaliteli bir `service_name` sütununu art arda gelen aynı değerleri gruplayacak biçimde sıralamak RLE benzeri örüntüleri güçlendirebilir, fakat zaman filtresi için yararlı sıralamayı bozabilir.

Şema tasarımında sıkıştırma kazanımı ile arama seçiciliği birlikte ölçülür. Sıralama anahtarını yalnız yüksek sıkıştırma için seçmek, yaygın `WHERE tenant_id = ... AND event_time BETWEEN ...` filtresinin bütün veri parçalarını taramasına neden olabilir. Sıkıştırılmış bayt başına sorgu maliyeti; okuma hacmi, çözme işlem süresi ve elenen granül oranı bir arada değerlendirilerek hesaplanır.

### 8.6. Kodlayıcı Zincirleri ve Sıkıştırma–CPU Maliyet Dengesi

`CODEC(Delta, ZSTD)` gibi bir zincir dönüşümü sıkıştırmadan önce uygular. Codec seçimi INSERT CPU yükü, disk kapasitesi, okuma CPU maliyeti ve sorgu sıklığı arasında dengedir. Toplu testte sıkıştırılmış bayt ve sorgu süresi birlikte kaydedilir; yalnız oran seçimi yeterli değildir.

Codec seçimi `compressed_bytes` ile ölçülürken veri yükleme CPU süresi ve sorgudaki açma hızı da raporlanmalıdır. Örneğin ZSTD'nin daha yüksek sıkıştırma oranı depolama I/O'sunu azaltabilir; ancak kısa, cache-hot sorgularda CPU çözme maliyeti belirleyici hale gelebilir. Delta veya Gorilla gibi dönüştürücü codec'ler, genel amaçlı sıkıştırmanın öncesinde uygun veri desenlerini daha kompakt biçime çevirebilir. Verinin niteliği bilinmeden tüm kolonlara tek codec zinciri atamak ölçümden bağımsız bir tercihtir.

### 8.7. Vektörleştirme ve Bellek Tahsisi

sütun yönelimli blokların toplu işlenmesi operatör çağrı giderini azaltabilir. Ancak büyük ara `Array`, yüksek kardinaliteli hash tablo veya geçici kolonların gereksiz materyalleştirme'ı bellek baskısı üretir. Performans analizi hem veri kaynağı hem yürütme sırasında oluşan ara temsilleri kapsar.

Bütün ara sonuçların satır başına ayrı nesne olarak temsil edilmesi allocation ve pointer-chasing maliyetini yükseltir. Sütun blokları üzerinde toplu hesaplama, bu maliyetin bir bölümünü sabit sayıda tahsisle karşılayabilir. Bununla birlikte yüksek kardinaliteli `GROUP BY` ve `JOIN` sırasında hash tabloları yine büyük bellek alanları kullanır. Uygun performans ölçümü, toplam CPU zamanını ve işlem başına ayrılan baytı ayrı verir; yalnız iş parçacığı sayısındaki artışı hızlanma saymaz.

## Ünite 9: Donanım Mimarisi ve Analitik Sorgu Maliyetleri

Analitik sorgunun fiziksel maliyeti diskten okunacak veri, CPU'nun çözümleyeceği kodlama ve ara sonuçların bellekteki hareketi arasında bölünür. Yalnız CPU yüzdesine bakmak darboğazı belirlemez: yüksek çekirdek kullanımı yararlı paralellik de olabilir; düşük CPU kullanımı uzak depolama beklemesini gösterebilir. Veriyi daha sıkı sıkıştırmak disk baytını düşürürken çözücü maliyetini artırabilir. Bağımsız işlemlerin eşzamanlı yürütülmesi tek bir sorgunun hızlanmasıyla eşdeğer değildir.

Bir sütun taramasının alt sınırı teorik olarak byte/bant genişliğiyle sınırlansa da modern CPU'larda verinin önbellekten sürekli akması her zaman işlemciyi tam kullanıma ulaştırmaz. Ayrıştırma, JSON alanı açma, hash erişimi, düşük seçicilikli dallanma ve tahsis işlemleri kaynağı değiştirebilir. Vektörleştirilmiş yürütme birçok satır için operatör maliyetini toplulaştırır; SIMD ise o toplu işlemin belirli adımlarını aynı makine komutu üzerinden paralel gerçekleştirebilir. Vektörleştirme bulunması her aşamada AVX komutu kullanıldığı anlamına gelmez. Sorgu A'da CPU kullanımının artması daha yüksek işlem hacmi'la birlikte gerçekleşiyorsa olumlu olabilir; sorgu B'de bellek bant genişliği doygunken ek thread açılması kuyruk ve önbellek contention doğurabilir. Bu yüzden süre, işlenen byte, cycles-per-byte ve bellek trafik ölçüleri birlikte yorumlanır.

### 9.1. Satır ve Sütun Yönelimli Depolamanın NSM–DSM Karşılaştırması

NSM satırın alanlarını yan yana; DSM aynı sütunun değerlerini toplu saklar. Bir tabloda 40 sütundan yalnız üçü seçiliyorsa sütun yerleşimi önemli ölçüde daha az bayt okuyabilir. Buna karşılık tek satırın bütün alanlarını sık sık güncelleyen iş yükünde sütun kopyalarının düzenlenmesi farklı maliyet doğurur.

Satır yönelimli NSM düzeninde bir kaydın alanları birlikte depolanır; DSM'de her sütunun değerleri bitişik bloklarda tutulur. Tabloda 40 alan bulunup sorgu yalnız 3 alanı kullanıyorsa DSM gereksiz sütunları okumayabilir. Bunun karşılığında tek satırın bütün alanlarını yeniden oluşturmak için sütunların aynı satır konumları üzerinden eşleştirilmesi gerekir. Karşılaştırma, veri tipi genişliği, sıkıştırma ve satır seçiciliği belirtilmeden yalnız kayıt sayısıyla yapılmamalıdır.

Sütun yönelimli DBMS araştırmalarında C-Store (Stonebraker ve diğerleri, 2005) fiziksel düzen ve projeksiyonları, MonetDB/X100 (Boncz, Zukowski ve Nes, 2005) ise vektörleştirilmiş yürütmeyi temel tasarım kararları olarak ele alır.

### 9.2. Disk, Sayfa Önbelleği ve G/Ç Bant Genişliği

Etkin bant genişliği fiziksel diskin ilan edilen en yüksek hızına eşit değildir. Küçük parça erişimleri, uzak nesne depolama gecikmesi ve sayfa önbelleği erişim düzeni sonucu değiştirir. T_salt_okuma ≥ B_gerekli/β_sürdürülebilir alt sınırı, ayrıştırma ve koordinasyon maliyetlerini ayrıca gerektirir.

Diskten gelen veri işletim sisteminin sayfa önbelleğinde bulunuyorsa aynı tarama ikinci çalışmada fiziksel disk okumayabilir. Bu nedenle soğuk ve sıcak ölçümde `read_bytes` ile fiziksel disk I/O sayaçlarının farklı sonuçlar vermesi beklenebilir. Diskin sıralı okuma kapasitesi, rastgele erişim gecikmesi ve nesne deposu gecikmesi birbirinin yerine kullanılamaz. Paralel tarama iş parçacığı sayısını artırmak, toplam aygıt bant genişliği doygunluğa ulaştıktan sonra veri aktarımını büyütmez; bellek ve CPU rekabetini artırabilir.

### 9.3. CPU Önbelleği, NUMA ve Bellek Hiyerarşisi

L1/L2/L3 önbellek kapasitesi, önbellek satırı boyutu, NUMA uzaklığı ve bellek bant genişliği toplu işlemeyi etkiler. Sütun üzerinde ardışık tarama öngörülebilir erişim sağlayabilir. Büyük hash JOIN tablosunda düzensiz adres erişimleri ve tahsis baskısı, tarama hızından çok daha belirleyici olabilir.

L1/L2/L3 önbellek gecikmeleri, ana belleğe erişimden farklı mertebededir. Sıkıştırılmış sütun bloklarının ardışık çözülmesi CPU önbellek yerelliğini iyileştirebilir; yüksek kardinaliteli hash agregasyonunda rastgele bellek erişimleri bu avantajı azaltabilir. NUMA sistemde uzak bellek düğümüne erişim maliyeti iş parçacığı yerleşimine bağlıdır. Bu nedenle CPU çekirdeği sayısı, tek başına analitik sorgunun ölçeklenme katsayısı olarak kullanılmamalıdır.

Modern analitik tarama, işlemciyi her zaman hesaplama gücüyle sınırlamaz. Örneğin bir operatörün her satırda 20 bayt bellek aktarımı yapıp 4 kayan noktalı işlem gerçekleştirmesi durumunda aritmetik yoğunluk 0,2 FLOP/bayt olur. Bellek bant genişliği 100 GB/s, işlem kapasitesi 2 TFLOP/s ise Roofline üst sınırı min(2000, 0,2 × 100) = 20 GFLOP/s'dir. Daha hızlı vektör komutları tek başına bu sınırı değiştirmez; daha az veri okuma, sıkıştırılmış sütunda doğrudan işlem veya daha iyi önbellek yerelliği gerekir. Bu hesap, gerçek sorgudaki filtreleme ve dallanma maliyetleri hesaba katılmadan elde edilen kuramsal sınırdır.

NUMA düzeninde uzaktaki soketin belleğinden okuma ek gecikme ve bant genişliği paylaşımı doğurabilir. CPU çekirdeği sayısını artırmak, veri ve yürütme iş parçacıklarının düğümler arasında uygun dağılımı olmadan doğrusal hızlanma sağlamaz. Bu nedenle aynı sorgunun çekirdek ve iş parçacığı ayarları sabitken CPU kullanımını, okunmuş baytı ve bellek kullanımını birlikte incelemek gerekir.

### 9.4. SIMD SSE/AVX ve Vektörleştirilmiş Yürütme Ayrımı

SIMD, tek bir işlemle birden fazla veri öğesinin işlenmesini sağlayan işlemci komut ailesidir. SSE, AVX2 ve AVX-512 desteği; hedef CPU, derleme seçenekleri ve ilgili operatörün uygulamasına bağlıdır. Bir ClickHouse sorgusunda sütunların vektörler halinde taşınması her operatörün mutlaka SIMD komutu kullandığını göstermez. Toplu işleme, sanal fonksiyon çağrısı ve döngü kontrolü giderlerini azaltabilir; SIMD ise özellikle karşılaştırma, bit işlemi, aritmetik ve bazı tarama algoritmalarında ek hızlanma sağlayabilir.

Örneğin her biri 32 bit olan 8 değerin aynı AVX2 vektör komutuyla karşılaştırılabilmesi teoride sekizli veri paralelliği sağlar; bellekten yükleme, mask üretimi, sonuç yazımı ve veri bağımlılıkları toplam hızlanmayı daha düşük tutabilir. Gecikme `T ≈ max(B/β, I/ρ)` ile sınırlandığında, bellek bant genişliği doymuş bir taramada daha geniş SIMD kaydı kullanmak tek başına süreyi düşürmeyebilir. Bu yüzden işlemci sayaçları ve okunan bayt, sorgu planıyla birlikte yorumlanır.

SIMD, tek komutla birden fazla veri elemanı üzerinde işlem yapılmasını sağlar; vektörleştirilmiş sorgu yürütme ise kayıtların küçük gruplar halinde operatörler arasında taşınmasını ifade eder. İkinci yöntem SIMD olmadan da çağrı ve dallanma maliyetini azaltabilir. SSE ve AVX komut kümelerinden yararlanma derleme hedefi, CPU desteği ve algoritmanın veri tipine bağlıdır. Metin ayrıştırma ve değişken uzunluklu veri işleme işlemlerinde SIMD kazanımı sabit genişlikli sayısal taramayla aynı olmayabilir.

Roofline modelinde sürdürülebilir işlem hızı yaklaşık P ≤ min(P_tepe, I × B_sürdürülebilir) ile sınırlanır. Burada I = işlem sayısı / bellekten taşınan bayt aritmetik yoğunluğu, B ise ölçülen bellek bant genişliğidir. Örneğin 8 baytlık iki sütunun okunup satır başına iki aritmetik işlem yapıldığı bir taramada I ≈ 2/16 = 0,125 işlem/bayt olur. B = 80 GB/s ise yalnız bellek aktarımı dikkate alındığında yaklaşık 10 milyar işlem/s üst sınırı elde edilir; bu değer gerçek sorgu işlem hacmini göstermez. Şubeleme, filtreleme, sıkıştırma çözümü, hash tabloları ve veri erişim örüntüsü ek sınırlar getirir.

Verinin diskten okunduğu ilk taramada darboğaz SSD aktarımı veya dağıtık nesne deposu olabilir. Bellek önbelleği sıcak olduğunda aynı sorgunun darboğazı CPU çevrimlerine kayabilir. Başarım karşılaştırması sonuçları bu nedenle soğuk ve sıcak okumaları açıkça ayırmalı, önbellek temizleme prosedürünü ve aynı anda çalışan sorgu sayısını belirtmelidir.

### 9.5. Tarama, GROUP BY, JOIN ve Dağıtık Veri Aktarımının Karmaşıklığı

Scan maliyeti okunan bayta; hash GROUP BY yaklaşık işlenen satır sayısına ve grup kardinalitesine; JOIN maliyeti build/probe, eşleşme çokluğu ve bellek davranışına bağlıdır. Dağıtık GROUP BY yerel kısmi agregasyonla ağ yükünü azaltabilir, ancak yüksek kardinalite ara durum boyutunu büyütür.

Hash GROUP BY için n giriş satırı ve k farklı anahtar olduğunu varsayalım. Ortalama sabit hash erişimi altında beklenen işlem sayısı O(n), ek durum belleği yaklaşık O(k) olur; çakışma, rehash ve yüksek anahtar genişliği sabit katsayıları artırır. Sort tabanlı GROUP BY alternatifinde O(n log n) karşılaştırma maliyeti görülebilir; ancak girdi anahtara göre sıralıysa çok daha uygun akış işleme toplama mümkündür. Aynı şekilde hash JOIN'de build R, probe S olmak üzere ortalama O(|R|+|S|) değerlendirmesi yalnız bellek ve hash varsayımları altında geçerlidir. Sonuç eşleşme sayısı büyükse çıktı üretimi de maliyete katılır.

Tarama maliyeti okunan baytla yaklaşık doğrusal büyürken hash agregasyonu beklenen durumda işlenen satır sayısına bağlıdır; ancak hash tablosunun boyutu grup kardinalitesiyle büyür. Sıralama tabanlı agregasyon için karşılaştırma sayısı genellikle O(N log N) ölçeğindedir. Dağıtık `GROUP BY` sorgusunda yerel kısmi durumların ağdan aktarılması ara veri miktarını azaltabilir. Çok yüksek kardinaliteli bir grupta ise ara durumların sayısı ham giriş satırlarına yaklaşarak ağ maliyetini yeniden baskın hale getirebilir.

### 9.6. Amdahl Yasası, Eşzamanlılık ve Paralellik Üst Sınırları

Amdahl yasasına göre hızlanma S(p)=1/((1−f)+f/p) olup f paralelleştirilebilir iş oranıdır. Koordinasyon, tek düğüm darboğazı ve veri aktarımı bu sınırı daha da düşürür. Dört kat çekirdek sayısı tek sorgunun dört kat hızlanmasını zorunlu kılmaz.

Amdahl yasası, işin s oranındaki seri bölümünün toplam hızlanmayı sınırladığını ifade eder: S(P) = 1 / (s + (1 − s)/P). Örneğin sorgunun %10'u kaçınılmaz seri aşamaysa sonsuz işlemci varsayımında bile hızlanma üst sınırı 10 kattır. Gerçekte scheduler maliyeti, bellek bant genişliği, birleştirme ve ağ haberleşmesi de vardır. Bu nedenle `max_threads` artırımı yalnız paralel yürütülebilen bölüm yeterince büyükse yarar sağlar.

### 9.7. Roofline Modeli ve CPU–Bellek Darboğazı

Roofline yaklaşımı operasyonun aritmetik yoğunluğunu FLOP/bayt cinsinden değerlendirir; bellek bant genişliği sınırlı operatörler ile hesaplama sınırlı operatörleri ayırmaya yardım eder. Analitik SQL için hash erişimleri, dallanmalar ve sıkıştırma çözücüsü de modele dahil edilmelidir.

Roofline modelinde gerçekleştirilebilir işlem hızı hesaplama tavanı ile bellek bant genişliğinin, aritmetik yoğunlukla çarpımından küçük olmalıdır: P ≤ min(P_tepe, β_bellek × I_aritmetik). Aritmetik yoğunluk, aktarılan bayt başına yapılan yararlı işlemi gösterir. Basit `SUM` taraması çoğu zaman bant genişliği sınırlıyken karmaşık sıkıştırma çözme ve ifade değerlendirme işlemleri CPU sınırlı olabilir. Bu sınıflandırma, aynı sorgunun SSD üzerinde ve önbellekten çalıştığında neden farklı darboğaz sergilediğini açıklar.

Analitik operatörlerin tamamı kayan nokta aritmetiği yapmadığı için klasik FLOP temelli roofline modeli veritabanına doğrudan taşınamaz. Sorgu özelinde yararlı işlem, işlenen satır, çözülen bayt, karşılaştırma veya hash probe olarak seçilirse birimler açıkça yazılmalıdır. Örneğin 800 milyon kaydın 6,4 GB sıkıştırılmış sütunundan okunup 2×10⁹ basit karşılaştırma yapıldığı varsayılsın. Etkin bellek bant genişliği 40 GB/s ise yalnız veri aktarımı alt sınırı yaklaşık 0,16 saniyedir. Karşılaştırma işlem hacmini 5 milyar/s ise hesaplama alt sınırı 0,4 saniyedir; ilki değil ikincisi baskın görünür. Gerçekte hash tablo erişimi, branch misprediction, önbellek miss ve ayrıştırma da ölçülmelidir.

Sorgu profiline `read_bytes`, çözülmüş sütun baytları, CPU zamanı, önbellek miss ve dökümlenmiş ara sonuç boyutu birlikte alınır. SIMD genişliğini iki katına çıkarmak, operatör bellek gecikmesine veya hash tablosu senkronizasyonuna bağlıysa iki kat hız sağlamaz.

## Ünite 10: ClickHouse İç Mimarisi ve Temel Soyutlamaları

Bir SELECT ifadesi doğrudan disk taramasına dönüşmez. Ayrıştırma, anlamsal çözümleme, planlama ve blok tabanlı yürütme birbirinden ayrı aşamalardır.

![ClickHouse sorgu işlem hattı animasyonu](https://alikoker.com.tr/svg/clickhouse-query-pipeline.svg "ClickHouse sorgu işlem hattı")


Bir ClickHouse sorgusu SQL çözümlemesi, anlamsal bağlama, mantıksal/fiziksel planlama ve işlemci hattı üzerinden yürütülür. Kaynak tablolar, disk üzerindeki veri parçaları ve sütun blokları okuma operatörleriyle sorgu hattına taşınır. Motorun C++ uygulaması SIMD ve bellek yönetimi optimizasyonlarına olanak verir; fakat gerçek darboğaz veri dağılımı, sorgu şekli ve G/Ç topolojisiyle ortaya çıkar.

Sorgu yürütme hattında kaynak işlemcileri farklı veri parçalarından sütun blokları okur; filtreleme ve ifade işlemcileri bunları dönüştürür; sıralama, toplulaştırma ve biçimlendirme işlemcileri daha sonraki aşamalarda çalışır. Ara verinin tek satır üzerinden fonksiyon fonksiyon ilerletilmesi, büyük hacimde çağrı ve dallanma maliyeti yaratabilir; blok işlemeyi amaçlayan yürütme modeli bu maliyeti sınırlamaya çalışır. Öte yandan bütün ara kolonların aynı anda fiziksel olarak oluşturulması bellek tüketimini artırabilir. İşlem hattı karmaşıklığı açısından temel trade-off veri akışını parçalara bölmek ile ara durumların birleşmesi gereken noktaları yönetmektir. Paylaşılan diskli/remote-object-store tasarımında okuma akışına ağ ve önbellek işlemleri eklenir; aynı sorgu planının farklı dağıtımda aynı bekleme süresine sahip olacağı varsayılamaz.

### 10.1. Depolama, Sorgu İşleme ve Entegrasyon Katmanları

ClickHouse'un mimarisi üç sorumluluk düzeyinde incelenebilir. Depolama düzeyinde tablo motorları sütun verisini, veri parçalarını (veri parçası), indeksleri ve birleştirme işlerini yönetir. Sorgu yürütme düzeyinde ayrıştırıcı ve çözümleyici SQL ifadelerini anlamlandırır; planlayıcı ile işlem hattı okuma, filtreleme, birleştirme, sıralama ve agregasyon işlemlerini çalıştırır. Entegrasyon düzeyinde istemci protokolleri, dış tablo motorları, dosya biçimleri ve mesajlaşma kaynakları bulunur. Bu bölümleme akademik bir soyutlamadır; sunucuda bütün bileşenleri birbirinden yalıtan üç bağımsız süreç bulunduğunu ifade etmez.

Veri alımında bir INSERT isteğinin kabulü, bloğun sıralanması, sıkıştırılması, veri parçası oluşturulması ve replikasyonunun tamamlanması farklı aşamalardır. Sorgulamada ise seçilecek veri parçası ve işaret aralıkları belirlendikten sonra sütunlar okunur; ara `Chunk` nesneleri işlemciler arasında aktarılır. Bu iki yol disk, CPU, bellek ve arka plan havuzlarında kaynak paylaşabilir. Bir sorgunun gecikmesini çözümlemek için yalnız HTTP yanıt süresini değil, okunan satır/bayt miktarını, eşzamanlı sorguları, arka plan birleştirme yükünü ve işlenen ara veri büyüklüğünü birlikte incelemek gerekir. İç mimarinin araştırma temeli Schulze ve diğerlerinin (2024) ClickHouse çalışmasıdır.

### 10.2. Yerel C++ Mimarisi ve Sunucu Yaşam Döngüsü

Sunucu başlatma sırasında yapılandırma ve üstveri yüklenir, arka plan havuzları oluşturulur, ağ uçları açılır. Normal kapatma veri parçası ve günlük durumunun güvenli sonlandırılmasıyla ilgilidir. Düşük seviye sınıf adları ve thread uygulamaları sürümden sürüme değişebilir.

C++ uygulamasında veri blokları çoğunlukla kolon dizileri olarak işlenir; gereksiz satır nesnesi tahsisinden kaçınılması yüksek işlem hacmi açısından önemlidir. Sunucu yaşam döngüsünde ayarların okunması, disk/üstveri yapılarının açılması, tablo motorlarının yüklenmesi ve arka plan görevlerinin başlaması farklı aşamalardır. Başlangıçta Keeper veya uzak depolamaya erişilememesi ile SQL parser hatası farklı operasyonel durumlardır. Başlangıç süreleri ve başarısızlık nedenleri ilgili log ve durum tablolarından ayrıştırılmalıdır.

### 10.3. Block, Column, Chunk ve İşlem Hattı Soyutlamaları

ClickHouse iç yürütme temsillerinde `Column` aynı türden değerleri; `Block` sütun adları, türler ve sütun verilerinin birlikte ele alınabildiği yapıyı; `Chunk` yürütme aşamaları arasında taşınan veri bloklarını temsil eder. Bunlar SQL düzeyindeki tablo, satır ve işlem kavramlarıyla birebir eşdeğer değildir. İşlem hattı işlemcileri girdi/çıktı bağlantıları üzerinden veri akışını tüketir ve üretir. Bir kaynak işlemci diskten sütunları okuyabilir, filter işlemcisi koşulu uygulayabilir, toplulaştırma işlemcisi hash durumlarını oluşturabilir ve sink işlemcisi sonuçları istemciye yazabilir.

Yürütme grafiğinin genişliği `max_threads` gibi ayarlarla ve okuma kaynağının bölünebilirliğiyle sınırlanır. Çok çekirdekli sunucuda tek parçalı, az granule'lü bir sorgu tüm çekirdekleri zorunlu olarak doldurmaz. Çıkışa yakın sonuç birleştirme, sıralama veya ağ üzerinden tek bir istemciye cevap iletme aşamaları paralel bölümün hızlanmasını sınırlar. Bir planın çok sayıda işlemci göstermesi eş zamanlı olarak hepsinin dolu ve üretken çalıştığını kanıtlamaz.

`WHERE` işlemcisi bir bloktaki seçilmiş satırları azaltırken `ARRAY JOIN` bir girdiden birden fazla çıktı satırı üretebilir; `GROUP BY` ise hash durumlarında birçok satırı bir anahtara indirger. Bu yüzden işlem hattının her bağlantısında satır sayısı, bayt miktarı ve çalışma zamanı farklıdır. İşlemcilerin backpressure mekanizması, yavaş bir tüketicinin önündeki sınırsız ara sonuç birikimini önlemek açısından temel bir yürütme özelliğidir.

### 10.4. Ayrıştırıcı, Çözümleyici, Planlayıcı ve Yürütücü Katmanları

Parser metni sözdizimsel yapıya dönüştürür; analyzer isimleri ve türleri çözümler, planner yürütme operatörlerini düzenler, executor fiziksel işlemcileri çalıştırır. Bu katmanların ayrımı `EXPLAIN AST`, `EXPLAIN PLAN` ve `EXPLAIN PIPELINE` çıktılarında gözlenebilir. Yanlış performans teşhisi çoğu zaman SQL metnine bakıp hangi fiziksel alanların okunduğunu ve hangi aşamada ara veri büyüdüğünü görmemekten kaynaklanır.

`EXPLAIN AST` sözdizim dönüşümlerini, `EXPLAIN PLAN` mantıksal/fiziksel operatörlerin ilişkisini, `EXPLAIN PIPELINE` ise yürütme hattındaki işlemci çoğulluğunu incelemek için kullanılır. İşlem hattı üzerindeki işlemci sayısı tek başına çekirdek kullanımına eşit değildir; bir aşamanın seri kalması toplam hızlanmayı sınırlayabilir. `ReadFromMergeTree` sonrasında filtre ve agregasyon operatörlerinin sırası, hangi sütunların erken okunacağını ve ara blok büyüklüğünü etkiler.

Plan aynı sorgu ve şema için sunucu sürümü, istatistiklerin varlığı, ayarlar ve optimizasyonların gelişimiyle değişebilir. Performans kaydında SQL metninin yanı sıra sürüm, ayarlar, tablo DDL'si, veri hacmi ve `EXPLAIN` çıktısı tutulmalıdır. Farklı iki planın yalnız düğüm adlarına bakılarak eşdeğer sayılması doğru değildir.

Sorgu iyileştiricisinin kararlarını çözümlemek için SQL'in eşdeğer biçimlerde yazılması tek başına yeterli değildir. Sorgunun kullanılan ClickHouse sürümünde `EXPLAIN AST`, `EXPLAIN PLAN` ve `EXPLAIN PIPELINE` ile incelenmesi farklı aşamaları ayırır: AST sözdizimini, plan mantıksal/fiziksel operatörleri, işlem hattı ise iş parçacıkları arasında yürütülecek işlemcileri gösterir. İki plan farklı olsa da sonuç eşdeğerliği ayrıca sınanmalıdır. Örneğin dış birleştirmelerde filtre koşulunun JOIN öncesine taşınması, NULL-üreten satırların varlığını değiştirebilir; sıradan iç birleştirmedeki dönüşümle aynı kural uygulanamaz.

Maliyet tabanlı planlama, veri dağılımını ve kardinalite tahminini gerektirir. Sorgu planlayıcısının belirli bir sürümde maliyet modelini kullanması, bütün operatörlerin küresel en iyi planını bulduğu anlamına gelmez. Yeni sürümlerde plan değiştiğinde karşılaştırma, veri kesiti ve ayarlar sabit tutularak yapılmalıdır.

### 10.5. Paylaşımsız ve Paylaşılan Diskli Dağıtımlar

Paylaşımsız mimaride bölütler kendi depolama ve işlem kaynaklarını taşır. Bulut tabanlı ayrık hesaplama/depolama yaklaşımında nesne depolama ve ara önbellek katmanları devreye girebilir. Ağ maliyeti ve üstveri koordinasyonu iki modelde farklıdır.

Paylaşımsız dağıtımda her düğüm verinin kendisine atanmış bölümünde çalışır ve ara sonuçları ağ üzerinden gönderir. Paylaşılan diskli türü yaklaşımlarda ortak depolamadan erişilen veri parçası üstverisinin tutarlılığı ile node-local önbellek geçersizleştirmesi önem kazanır. Bölüt sayısının değişmesi veri taşıma maliyeti yaratırken replica sayısının değişmesi aynı bölüt verisinin kopyalanması anlamına gelir. Mimarinin avantajını anlamak için veri sahipliği, coordinator rolü ve hata sınırları birlikte incelenmelidir.

### 10.6. Metrik, Sistem Tabloları ve Sorgu İçgözlemi

`system.parts`, `system.merges`, `system.query_log` ve `system.metrics` fiziksel durum ve yürütme belirtileri sağlar. Log tablolarının etkinliği ve saklama süresi yapılandırmaya bağlıdır. Sistem tablolarını okumak, otomatik olarak tüm sorgu planı veya tam kaynak tüketim profilini vermez.

Sistem katmanlarının hangi aşamada maliyet ürettiğini görmek için ilgili tablolar birbirini tamamlayacak şekilde kullanılır:

```sql
SELECT name, value FROM system.metrics ORDER BY name LIMIT 30;
SELECT database, table, count() AS active_parts
FROM system.parts
WHERE active
GROUP BY database, table
ORDER BY active_parts DESC
LIMIT 20;
```

`system.metrics` anlık değerlerden oluşur; uzun dönem kapasite çıkarımı için kontrollü zaman serisi gerekir.

### 10.7. Tarihsel ve Güncel Uygulama Farkları

Eski dökümanlardaki optimizer, projection ve mutation açıklamaları güncel sürümde aynı kalmayabilir. Tarihsel iç yapı yorumları mimari evrimi anlamak için korunur; uygulanabilir SQL ve yönetim ayarlarında sürüm doğrulaması esastır.

Eski uygulama ayrıntılarında bir indeks veya veri biçiminin belirli bir sınıf adıyla açıklanması, güncel sürümlerde aynı sınıfın bulunduğu anlamına gelmez. 2020 ve 2022'de yayımlanmış iç mimari örnekleri güncel resmi API sözleşmesi değil tarihsel teknik kaynak kabul edilmelidir. Öğretimde korunması gereken kalıcı kavramlar, veri parçalarının sıralı veri tutması, indeksle granül aralıklarının seçilmesi ve işlem hatlarının kolon blokları üzerinde çalışmasıdır; sürüme özel isimler ayrıca sürüm koşuluyla verilir.

## Ünite 11: MergeTree ve Fiziksel Veri Organizasyonu

MergeTree veriyi değişmez partiler halinde tutar. Sütun dosyaları, granüller ve marklar birlikte fiziksel okuma sınırını belirler.

![MergeTree part granül mark animasyonu](https://alikoker.com.tr/svg/mergetree-part-granule-mark.svg "MergeTree part granül ve mark yapısı")


MergeTree ailesinde INSERT tipik olarak bölüm ve sıralama anahtarına göre düzenlenen yeni bir immutable veri parçası oluşturur. Okuma işlemi aktif veri parçalarından sütun aralıkları seçer; arka plan birleştirme işlemleri birden çok veri parçasını daha büyük parçalar haline getirir. Bu yaklaşım geleneksel tekil satır güncelleme merkezli B+ ağaç depolamasından farklıdır. Depolamanın fiziksel ayrıntıları `system.parts` ve `system.parts_columns` üzerinden incelenebilir.

MergeTree'nin parça bazlı düzeni INSERT'in atomik görünürlük birimi hakkında düşünmeyi sağlar. Yeni veri veri parçasını bütün gerekli sütunlarıyla ve metadata'sıyla oluşturulduğunda etkin hale gelir; arka plandaki birleştirme yeni veri parçasına geçiş yapar. Ancak kullanıcı tarafından görülen atomiklik biriminin server/topoloji/motor koşulları, bir uygulamanın bütün yazma işlemini ortak işlem olarak kabul etmek için yeterli değildir. Fiziksel veri parçası dosyalarını elle silmek, katalog ve replikasyon üstverisini bozabilir. Bir tabloda `system.parts` incelenirken `active = 1`, bölüm ve disk dikkate alınmalıdır. Çok küçük part'larla büyük veri parçalarının birlikte bulunması normal geçiş durumu olabilir; sürekli büyüyen küçük veri parçası birikimi ve birleştirme kuyruğu kapasite işaretidir. İnceleme yalnız bir anlık sayım değil zamana göre bir eğilim olmalıdır.

### 11.1. Değişmez Veri Parçaları ve Yaşam Döngüleri

Aktif veri parçası sorguların okuyabileceği veri kümesini temsil eder; birleştirme tamamlandığında yeni veri parçası görünür olur, eskileri yaşam döngüsü içinde kaldırılır. Veri parçaları rastgele satır eklenerek büyütülmez; yeni insert yeni veri parçası oluşturabilir. Görünürlük ve temizleme aşamaları ayrı ele alınır.

INSERT ile oluşturulan veri parçası, belirli bölüme ait sıralanmış bir satır kümesidir. Yeni INSERT genellikle mevcut veri parçası dosyalarını yerinde değiştirmez; yeni veri parçası oluşturulur. Arka planda birden çok veri parçası birleşerek daha büyük yeni veri parçasına dönüşebilir ve eski veri parçalarının üstverisi devreden çıkarılır. Bu yöntem yazma sırasında rastgele küçük disk değiştirmelerini azaltır, ancak geçici disk alanı ve birleştirme kaynak tüketimi gerektirir. `active` alanı bakımından veri parçası sayısı hesaplanırken eski veri parçaları ayrıca değerlendirilmelidir.

### 11.2. INSERT, Sıralanmış Akışlar ve Veri Parçası Oluşturma

INSERT verisi bloklara ayrılır ve tablo anahtarlarına göre sıralanarak veri parçası olarak yazılabilir. Çok küçük blokların art arda gönderilmesi veri parçası sayısını artırır. Kalıcı tekilleştirme veya UPDATE semantiği için INSERT'in başarılı olması tek başına yeterli değildir.

Bir INSERT bloğunun veri parçası olarak yazılması sırasında hedef bölüme göre ayrım, sıralama anahtarına göre sıralama, sütun akışlarının sıkıştırılması ve indeks/işaret üstverisinin üretilmesi gerekir. Tek INSERT birden fazla bölüme veri içeriyorsa birden fazla veri parçası oluşabilir. Çok küçük isteklerin sıklıkla yapılması sunucuyu küçük veri parçası üretimine zorlayarak birleştirme yükünü yükseltir. Parça ekonomisi yalnız toplam satır sayısına değil, parti içindeki bölüm dağılımına bağlıdır.

### 11.3. Wide ve Compact Veri Parçalarının Dosya Düzeni

Wide biçiminde sütunlar için ayrı akış dosyaları, Compact biçiminde küçük veriler için daha birleşik dosya yerleşimi kullanılabilir. Eşikler ayarlarla ve sürümle ilişkilidir. Daha az dosya sayısı her koşulda daha az okunan byte anlamına gelmez; okuma profili gözlenmelidir.

`Wide` veri parçası yerleşiminde sütunların ayrı akış dosyalarına sahip olması, yalnız gerekli kolonların okunduğu büyük sorgular için uygundur. `Compact` düzeni küçük INSERT part'larının dosya oluşturma yükünü azaltır; veri büyüdükçe birleşmeler sonucunda farklı fiziksel düzen oluşabilir. Dosya düzeni, bir veri parçasının mantıksal satır kümesi ve `ORDER BY` sırası hakkında farklı bir garanti getirmez. `system.parts` üzerinden `part_type`, `rows`, `bytes_on_disk` ve sütun boyutlarını karşılaştırmak fiziksel farkı somutlaştırır.

### 11.4. Sütun Dosyaları, İşaretler, Sağlama Toplamları ve Üstveri

Veri parçası üstverisi sütun türleri, bölüm, checksums, indeks ve işaret bilgilerini içerir. Checksums fiziksel bütünlük doğrulamasını destekler; iş alanlarının mantıksal doğruluğunu kanıtlamaz. İç dosya adları biçim ve sürüme bağlı olduğundan sabit sözleşme olarak kullanılmamalıdır.

Bir veri parçasının sütun veri akışları ve işaret üstverisi, okumanın nereden başlayacağını belirlemek için birlikte değerlendirilir. Checksum dosyaları bozuk veya eksik dosyaları teşhis etmeye yardımcı olur; checksums'ların varlığı harici depolama katmanının bütün hata türlerini önlediği anlamına gelmez. `system.parts`, `system.columns` ve `system.part_log` gibi tablolar veri parçası boyutu, yazma sıklığı ve arka plan hareketlerinin ölçülmesine olanak tanır. İç dosya adları ve uzantıları veri parçası biçimine göre değişebilir; belirli uzantılar kalıcı format sözleşmesi gibi sunulmamalıdır.

Wide veri parçası biçiminde sütun akışları ayrı dosyalarda, Compact veri parçası biçiminde birden fazla sütunun akışları ortak fiziksel dosyalarda yer alabilir. Her iki durumda da mantıksal sütun erişimi korunur; dosya sayısı ve küçük INSERT maliyeti farklılaşır. Fiziksel dosyaları inceleyen otomasyon, belirli bir `.bin` veya `.mrk2` uzantısının bütün sunucu sürümlerinde bulunacağını varsaymamalıdır.

Bir veri parçasının veri okunurluğuna ilişkin üç farklı hata sınıfı vardır: kontrol toplamı uyumsuzluğu (fiziksel bozulma), beklenen kolonun yanlış tipte çözümlenmesi (şema/format uyuşmazlığı) ve sorgunun başarılı olup yanlış iş alanı sonucunu üretmesi (mantıksal hata). İlk ikisi motor veya yedek doğrulama sırasında yakalanabilir; üçüncüsü için kaynak-toplam karşılaştırmaları ve alan invariant'ları gerekir.

### 11.5. Granül, İşaret ve Fiziksel Okuma Birimleri

Granül indeksin işaret ettiği ardışık satır aralığıdır. Varsayılan indeks granularity sıkça 8192 satırdır, ancak adaptive granularity ve ayarlar gerçek işaret başına satır sayısını değiştirebilir. İşaret yalnız birincil indeksin işaret ettiği konumu değil sütun okumasının başlangıcını da ilişkilendirir.

Bir veri parçası 8.192.000 satır içeriyorsa ve her granül 8192 satırsa yaklaşık 1000 işarete bölünür. `service_id = 42` filtresi iyi sıralamada yalnız 12 granül gerektirirse kaba tarama üst sınırı 12×8192 = 98.304 satırdır. Bu sınır, `PREWHERE`, veri tipleri, son granül boyutu ve indeks granularity farklılıklarından bağımsız bir üst düzey örnektir; verilerin 98.304 satırının tamamının her sütununun okunacağı anlamına gelmez.
```sql
EXPLAIN indexes = 1
SELECT service_id, count()
FROM events
WHERE service_id = 42
  AND event_time >= toDateTime64('2026-10-01 00:00:00', 3, 'UTC')
  AND event_time < toDateTime64('2026-10-02 00:00:00', 3, 'UTC')
GROUP BY service_id;
```
Planın parça/granül sayılarını, gerçek yürütmenin `read_rows`, `read_bytes` ve bellek tüketimiyle karşılaştırmak gerekir.

Bir veri parçasının satırları sıralama anahtarına göre düzenlenmiştir. `index_granularity` sabit satır hedefi kullanıldığında granül yaklaşık belirlenen satır sayısını kapsar; adaptive granularity etkin olduğunda bayt boyutuna bağlı sınırlar da uygulanabilir. Seyrek indeks, her satırın disk adresini değil granül başlangıçlarını temsil eder. Bu nedenle eşitlik filtresi tek satır döndürse bile motor ilgili granül ve sıkıştırma bloğunun tamamını veya bir bölümünü okuyabilir.

Örnek hesapta `R=100.000.000`, granularity hedefi `g=8192` kabul edilirse yaklaşık `ceil(R/g)=12.208` işaret düzeyi bulunur. `tenant_id,event_time` sırasına sahip bir tabloda belirli tenant'ın bir günlük kayıtları yan yana tutuluyorsa indeks daha az işaret aralığı seçebilir. Ancak `event_time` ilk anahtar olduğunda tenant verisi zaman boyunca karışabilir. İki sorgu ailesinin birlikte hızlı olması isteniyorsa fiziksel düzen, projection veya ayrı serving tablosu seçenekleriyle ölçülür.

Granül ile sıkıştırma bloğu birebir eşdeğer değildir. `PREWHERE` seçici sütunu önce işleyebilir; kalan sütunların gereksiz bloklarını açmadan satırları elemek için maske üretir. Sistem tablolarında kaydedilen `marks`, `rows`, `bytes_on_disk` gibi alanlar ile `EXPLAIN indexes = 1` çıktıları fiziksel okuma açıklamasının nicel kanıtını sağlar. Veri değiştikçe veri parçası sayısı, işaret dağılımı ve birleştirme davranışı da değiştiğinden aynı şema farklı dönemlerde farklı sonuç üretebilir.

İndeks adımı satır bazında sabit kabul edilmemelidir. Varsayılan `index_granularity` satır sayısı sınırı sağlasa bile `index_granularity_bytes` ve değişken satır boyutları adaptif granül oluşumunu etkileyebilir. Birincil indeks işaret değerleri seçilmiş sıralama anahtarını temsil eder; ikincil skipping index dosyalarındaki aralıklar farklı granularity çarpanlarıyla düzenlenebilir. Bir sorgunun `rows_read` değeri, seçilen işaret sayısının varsayılan granularity ile çarpımından sapabilir.

Örneğin sıralı `(tenant_id,event_time)` anahtarında yalnız `event_time` için aralık filtresi uygulamak, tenants arasında zamanlar iç içe bulunduğundan beklenen budamayı sağlamaz. Aynı filtre `tenant_id = ?` ile birleştirildiğinde seçilebilen key-prefix aralığı daralır. `EXPLAIN indexes = 1` ile işaret/veri parçası budaması; `system.query_log` ile fiilen okunan bayt karşılaştırılarak karar verilir. Primary index'in sparse olması, `PRIMARY KEY` tanımının SQL'deki benzersizlik garantisiyle karıştırılmamasını gerektirir.

8192 satırlık granularity ve 100 milyon satır için idealize edilmiş işaret sayısı ⌈100.000.000/8192⌉ = 12.208'dir. Ancak granül boyutu bazı koşullarda bayt sınırına göre değişebilir, birden fazla veri parçası ayrı işaret dizileri taşır ve indeks ile işaret dosyalarının gerçek boyutu anahtar tipine bağlıdır. Bir filtre yalnız 50 eşleşen satır döndürürken 12 granül okunuyorsa en az 98.304 satırlık fiziksel aralığın değerlendirilmesi gerekebilir. Bu değer sorgunun kaç satır okuduğuna eşit kabul edilemez; seçilen sütunlar, önbellek ve geç filtreleme ayrı katmanlardır.

Granül sınırlarının etkisini karşılaştırmak için `EXPLAIN indexes = 1` çıktısıyla seçilen veri parçaları/granules sayılarını, `system.query_log` üzerinden `read_rows` ve `read_bytes` değerlerini birlikte incelemek gerekir. Çıktı satır sayısı küçükken fiziksel okumalar büyükse sorgu sonucundan değil fiziksel yerleşimden hareketle optimizasyon yapılır.

### 11.6. İşaret Önbelleği, Dosya Sistemi Önbelleği ve Disk Yerleşimi

İşaret önbelleği indeks işaretlerinin, dosya sistemi veya kullanıcı alanı önbellek ise veri bloklarının okunma maliyetini etkiler. Uzak nesne depolamada ağ RTT ve önbellek hit oranı daha belirleyici olabilir. Sıcak önbellek başarım karşılaştırmasını ilk sorgunun soğuk okuma maliyetini gizleyebilir.

İşaret önbelleği, indeks üzerinden seçilen granül başlangıç bilgilerine hızlı erişimi hedefler. Dosya sistemi önbelleği ise işletim sistemi veya ClickHouse yönetimli önbellek katmanlarında veri bloklarının yeniden kullanımını etkiler. Her iki katmanın aynı metrikle izlenmesi doğru değildir: işaret önbelleği hit oranı yüksekken sıkıştırılmış veri blokları yine diskten okunabilir. Sorgu ölçümünde `read_rows`, `read_bytes`, fiziksel disk okuması ve önbellek hit oranları birlikte yorumlanmalıdır.

### 11.7. Veri Parçası İçeriğinin Sistem Tablolarıyla İncelenmesi

`SELECT partition, name, rows, bytes_on_disk, level FROM system.parts WHERE database = currentDatabase() AND table = 'events' AND active` veri parçası sayısını ve büyüklüklerini incelemek için temel sorgudur. Uzun süre birikmiş küçük aktif veri parçaları kötü insert partileri veya yetersiz birleştirme kapasitesine işaret edebilir.

Veri parçalarının satır ve disk büyüklüğünün karşılaştırılması:

```sql
SELECT
    partition,
    count() AS part_count,
    sum(rows) AS row_count,
    formatReadableSize(sum(bytes_on_disk)) AS disk_size
FROM system.parts
WHERE active AND database = currentDatabase() AND table = 'events'
GROUP BY partition
ORDER BY partition;
```

Veri parçası sayısının artışı mutlak hata değildir; aynı büyüme eğilimi birleştirme kuyruğu ve INSERT hızlarıyla birlikte yorumlanır.

Örneğin `system.parts` sorgusuyla aktif veri parçaları bölüm bazında sayılabilir; `system.merges` çalışan birleşmelerin ilerleyişini gösterir. Aktif olmayan veri parçalarını da toplama dahil etmek kapasiteyi olduğundan yüksek gösterir. Bir bölüm içinde çok sayıda küçük veri parçası bulunması çoğu zaman INSERT sıklığı ve birleşme kapasitesiyle ilişkilidir. Dosya sisteminden rastgele veri parçası silmek üstveri ve replikasyon bütünlüğünü bozabileceği için tanılama yetkisiyle bakım yetkisi ayrılmalıdır.

## Ünite 12: Sıralama Anahtarları ve Seyrek Birincil İndeks

ClickHouse birincil indeksi her satırı işaretleyen yoğun bir B-tree değildir. Sıralı anahtar uzayında seyrek mark noktaları üzerinden uygun granül aralıkları seçilir.

![Seyrek birincil indeks budama animasyonu](https://alikoker.com.tr/svg/sparse-primary-index-pruning.svg "Seyrek birincil indeks budaması")


MergeTree birincil indeksi satır başına işaret taşıyan benzersiz B-tree değildir. Sıralanmış veri parçası üzerinde granül başlangıç değerleri için seyrek bir erişim dizini kullanır. `ORDER BY` fiziksel düzeni, `PRIMARY KEY` dizindeki önek alanları belirtir; key değerlerinin tekrarı normaldir. Sorgunun tipik filtreleri bu sıranın başında bulunmuyorsa çok sayıda granül taranabilir. Anahtar seçimi depolama düzeni, sıkıştırma verimi, sorgu filtresi ve INSERT maliyeti arasında dengedir.

Birincil indeks için aranan koşul `service_id = 17 AND event_time BETWEEN t₀ AND t₁` olsun. `(service_id, event_time)` düzeninde 17 değerleri büyük ölçüde ardışık bulunduğundan zaman aralığı yalnız ilgili servisin fiziksel segmentinde sınanabilir. `(event_time, service_id)` düzeninde ise tüm servislerin dar zaman aralığı içinde sıralanması daha geniş bir segmenti gerektirebilir. Bu ayrımın büyüklüğü olay yoğunluğu ve servis dağılımına bağlıdır; düşük trafikli tek servis ile bütün servisleri kapsayan rapor farklı anahtarlardan yararlanır. Başarılı index pruning her zaman düşük sorgu gecikme demek değildir: seçilen granule'larda geniş `message` sütunu veya yüksek kardinaliteli JOIN bulunuyorsa kalan operatörler ağır olabilir. İndeksin gerçek katkısı `EXPLAIN indexes = 1` ile işaret düzeyinde, sistem sorgu log'uyla byte ve CPU düzeyinde ölçülür.

### 12.1. ORDER BY ile PRIMARY KEY Semantiği

`ORDER BY (tenant_id, event_date, event_id)` fiziksel sırayı tanımlar; `PRIMARY KEY (tenant_id, event_date)` seçilirse indeks daha kısa önekten oluşturulur. `PRIMARY KEY` benzersizlik kısıtı değildir. Anahtarın `ORDER BY` ifadesinin öneki olması gereken motorlarda özel kurallar kontrol edilmelidir.

`ORDER BY` MergeTree'nin satırların fiziksel sıralanmasını belirleyen ifadesidir; `PRIMARY KEY` bellekte tutulabilen seyrek birincil indeks için anahtar ifadesidir. Birincil anahtar, ilişkisel OLTP sistemlerindeki benzersizlik kısıtı değildir: aynı anahtar değerini taşıyan birden fazla ClickHouse satırı bulunabilir. `PRIMARY KEY` verilmezse çoğu MergeTree tanımında `ORDER BY` ifadesi birincil anahtar olarak kullanılır. Ayrı belirtildiğinde birincil anahtarın sıralama anahtarının ön eki olması beklenir; kullanılan motor/sürümün kısıtları doğrulanmalıdır.

Örnek: `ORDER BY (tenant_id, event_time, event_id)` ve `PRIMARY KEY (tenant_id, event_time)` kullanıldığında `event_id` fiziksel düzeni belirlemeye devam ederken birincil indeksin anahtar belleği daha dar tutulabilir. `event_id` ile tekil sorgulama ise anahtarın sol ön eki olmamasından dolayı geniş granül aralıklarını okumaya devam edebilir. `PRIMARY KEY`e daha fazla sütun eklemek disk üstünde ek ikincil B-tree yaratmaz; bellekte tutulan indeks bileşimini değiştirir. Anahtar dizilimi en çok yapılan WHERE ve ORDER BY sorgularıyla ilişkilendirilmelidir.

### 12.2. Seyrek Birincil İndeks ve İşaret Aralıkları

Seyrek dizin her satır için işaret tutmadığından bellekte küçüktür; karşılığında eşleşen granül içindeki ilgisiz satırların okunması gerekebilir. Okunacak işaret aralıkları ikili arama ve koşul analiziyle daraltılır. Kesin eşitlik filtresi bile uygun sıralama bulunmuyorsa çok sayıda işaret okuyabilir.

Birincil indeks her satıra tam konum saklamak yerine granül başlangıçlarındaki sorting-key değerlerini tutar. Filtre aralığına göre ilgili işaret aralıkları bulunur; gerçek satır koşulu okunan bloklar üzerinde tekrar değerlendirilir. Bu tasarım RAM ihtiyacını düşürür, ancak arama sonucunda granül içindeki eşleşmeyen kayıtların da okunmasına yol açabilir. Birincil indeksin çok seyrek seçilmesi noktasal sorguları, gereksiz sıkı seçilmesi indeks belleğini etkiler.

N satır, granül başına ortalama g satır ve indeks giriş başına k bayt için tek veri parçasının birincil indeks belleği kabaca M ≈ ⌈N/g⌉ × k olur. N = 800 milyon, g = 8192 ve k = 24 bayt varsayıldığında yaklaşık 97.657 giriş ve 2,23 MiB indeks alanı oluşur. Gerçek değer; demet bileşenleri, değişken uzunluklu tipler, veri parçası sayısı ve işaretlerin ayrı üstveri maliyetinden etkilenir. İndeks girişi sayısının N ile değil N/g ile ölçeklenmesi, seyrek indeksin temel tasarım tercihidir.

Tek bir granule'nin okunması bütün satırlarının sonuç döndürüleceği anlamına gelmez. Birincil indeks granül adaylarını bulur; `PREWHERE` ve `WHERE` koşulları gerçek satırları eler. Buna karşılık yüksek kardinaliteli ve sıralamayla ilişkisiz tekil alan için birincil indeks granül atlamayı çok az artırabilir. Böyle durumlarda ters indeks, skipping index veya projection seçeneklerinin maliyeti ayrı hesaplanır.

### 12.3. Granülerlik, İkili Arama ve Veri Budama

N satır, ortalama g satır/granül için kabaca ⌈N/g⌉ işaret vardır. N=1.000.000.000, g=8192 ise yaklaşık 122.071 işaret elde edilir; gerçek işaret sayısı veri parçası sınırları ve adaptive granularity nedeniyle değişir. İndeks maliyetinde veri parçası sayısının etkisi de bulunur.

Bir işaret aralığına erişim binary search ile daraltılabilir; ardından aynı sıkıştırılmış veri bloğu içinde birden fazla granül bulunabileceğinden fiziksel bayt fazlalığı doğabilir. `index_granularity` sabit satır sayısını temsil eden klasik ayar olmakla birlikte adaptif granularity ve byte tabanlı sınırlar devrede olabilir. Sorgudaki koşul sorting-key ön ekiyle uyumsuzsa index okunmasına rağmen az sayıda granül atlanır. Analiz, planın seçtiği işaret yüzdesi ile fiilen okunan bayt üzerinden yapılır.

### 12.4. Kardinalite, Anahtar Öneki ve Sorgu Örüntüsü

İlk anahtar sütununun sorgulardaki seçiciliği ile kardinalitesi birlikte değerlendirilir. Düşük kardinaliteli ama sık filtrelenen tenant veya servis alanı faydalı bir önek olabilir; tekil olay kimliğini ilk sıraya almak zaman-aralıklı taramayı bozabilir. İyi anahtar yalnız en yüksek kardinaliteli alanı öne almak değildir.

Bileşik sıralama anahtarında ilk sütunun düşük veya yüksek kardinaliteli olması tek başına doğru seçim ölçütü değildir. Seçici sorguların ön ekleri, veri geliş sırası, zaman dağılımı, tenant başına olay sayısı ve veri silme/TTL politikası birlikte değerlendirilir. `tenant_id` başta olduğunda tenant'a bağlı sorgu aralıkları daralabilir; yalnız zamana bağlı küresel taramalarda aynı düzen yeterli budamayı sağlamayabilir. `event_time` başta olduğunda zaman aralıklı sorgular hızlanabilir; bütün tenant verileri bir arada depolandığından tek tenant sorgusunda daha fazla granül okunabilir.

Anahtar tasarımında “yüksek kardinaliteli sütun sona” kuralı evrensel değildir. Ardışık zaman alanının büyük kardinalitesine rağmen sorguların çoğunda zaman filtresi varsa ilk konum rasyonel olabilir. İnceleme için en az üç şema üzerinde aynı veri ve sorgu karışımı karşılaştırılır; `read_rows`, `read_bytes`, işaret aralıkları, insert CPU, sıkıştırılmış boyut ve p95 birlikte kaydedilir. Yanlış anahtarın etkisi milyonlarca satırın okunmasına yol açabildiği için ilk şema kararı ikincil indeks eklemekten daha önemlidir.

Sıralama anahtarındaki ilk alan, filtrelerde en yaygın kullanılan alan olmak zorunda değildir; ilk alanın eşitlik/range koşullarında ne kadar granül atlatacağı belirleyicidir. Örneğin düşük kardinaliteli `tenant_id` ilk alan olduğunda tenant bazlı okuma için veri parçası içi aralıklar oluşur. `event_time` ikinci alan olduğunda tenant eşitliğiyle birlikte zaman aralığı daha etkin seçilebilir. Yalnız tarih aralığı kullanan sorgular bu düzenden aynı ölçüde yararlanmayabilir. Seçim gerçek filtre bileşimlerine ve seçicilik dağılımına dayanmalıdır.

### 12.5. Veri Dağılımına Göre Sıralama Seçimi

Gündelik olay analitiğinde `(servis_id, toDate(event_time), event_time)` servis ve zaman filtresinde başarılı olabilir; yalnız zaman filtresi baskınsa alternatif sıra daha uygundur. Aynı veri üstünde query_log iş yüküyle iki şema denenmeden varsayımsal hızlanma oranı verilmez.

`ORDER BY (service_id, event_time)` ile `ORDER BY (event_time, service_id)` fiziksel satır komşuluğunu farklı biçimde oluşturur. Servis + dar zaman penceresi sorgusu ilk düzende daha az aralık okuyabilirken zaman bazlı bütün servisleri karşılaştıran sorgu ikinci düzene yakınlık gösterebilir. Her iki sorgu ailesi eşit öncelikteyse projection veya ek özet yapı tercih edilebilir. İkinci fiziksel erişim yolunun saklama ve INSERT maliyeti, ilk tasarruf hesaplarına eklenmelidir.

### 12.6. Örnek Alan Modelleriyle Farklı Anahtar Karşılaştırmaları

Bir karşılaştırmada aynı veri üreticisi, veri parçası büyüklüğü, sıkıştırma ayarları ve sıcak/soğuk önbellek koşulları kullanılır. `EXPLAIN indexes = 1` seçilen granül sayısını incelemeye yardımcı olur. Farklı anahtarlar yalnız süreyle değil okunan satır/bayt ve INSERT maliyetiyle karşılaştırılır.

Aynı olay kümesinin iki farklı anahtarla oluşturulduğu kontrollü deneyde A şeması `(service_id, event_time)`, B şeması `(event_time, service_id)` kullansın. Yalnız `service_id` süzgeci bulunan sorgu A'da bitişik işaret aralıklarına daha iyi eşleşebilir; yalnız dar zaman aralığı bulunan sorgu B'de daha iyi budanabilir. Tek bir anahtar iki erişim biçimini eşit verimlilikte temsil etmeyebilir. Karar fonksiyonu olarak M = Σᵢ fᵢ × (α·Tᵢ + β·Bᵢ) + γ·W tanımlanabilir: fᵢ sorgu sıklığı, Tᵢ gecikme, Bᵢ okunan byte, W yazma/birleştirme maliyetidir. α, β, γ iş yükünün işletim önceliklerini ifade eden ağırlıklardır; bu biçim kuramsal modeldir, ClickHouse optimizer'ının kullandığı iç formül değildir.

Bir milyar kayıtta aynı tenant için sorgu yapıldığını varsayalım. Tenant kimliği ön ek olduğunda uygun dağılımla aranan satırlar bitişik aralıklarda bulunur; rastgele sıralanmış tabloda aynı tenant'ın satırları bütün granule'lere dağılabilir. Burada seçiciliği yalnız `1/tenant_sayısı` olarak hesaplamak yeterli değildir. Veri parçası sayısı ve her veri parçası içindeki granül dağılımı belirleyicidir; indeksin ayıkladığı işaret sayısı gerçek sorgu üzerinden okunmalıdır.

### 12.7. İndeksin RAM ve Disk Maliyetini Hesaplama

Birincil indeksin kaba boyutu granül sayısı × işaret başına anahtar değeri baytıdır; değişken uzunluk, encoding ve bellek içi temsil bu hesabı etkiler. Çok uzun anahtar prefix'i dizin belleğini büyütür. `system.parts.primary_key_bytes_in_memory` gibi alanların varlığı hedef sürümde doğrulanır.

Seyrek indeksin kaba bellek tahmini `M ≈ (R/g) × w` biçimindedir; R satır sayısı, g ortalama granül satırı, w anahtar tuple'ının bellekteki ortalama boyutudur. Bu tahmin veri parçası başına üstveri, değişken uzunluklu alanlar ve birincil indeksin başka temsil maliyetlerini içermez. Örneğin g=8192, R=10⁹ ve w=24 bayt için yalnız anahtar verisi yaklaşık 2,93 MB tutar; indeks bütünü bu değerden büyük olabilir. Satır başına bir B+ ağaç indeksi ile granül başına bir anahtar kaydı arasındaki önemli maliyet farkı buradan doğar.

Seyrek indeks için yaklaşık giriş sayısı `M ≈ ⌈R/g⌉` kabul edilebilir; R veri parçası içindeki satır sayısı, g ortalama granül satır sayısıdır. Anahtarın bir işaretteki serileştirilmiş boyutu p bayt ise yalnız işaretçi ve anahtar bileşenlerinin ilk kestirimi `M × p` olur. Bir veri parçası için 10⁹ satır, g=8192 ve p=24 bayt varsayımında 122.071 işaret ve yaklaşık 2,93 MB anahtar verisi ortaya çıkar. Bu yalnız kaba teorik hesaplamadır; gerçek indeks serileştirmesi, nullable bileşenler, bellek temsili, veri parçası sayısı ve üstveri ek yükü içermediğinden sistem tabloları/metrikleriyle doğrulanmalıdır.

Büyüklük açısından en kötü seçenek her zaman uzun anahtar değildir. Çok yüksek kardinaliteli ve seçiciliği düşük ilk anahtar alanı, sorguların çoğunda indeksin etkisini azaltırken anahtar belleğini artırabilir. Sıralama anahtarına bir sütun eklemeden önce filtrelerin dağılımı, sıkıştırma oranı ve insert sırasında sıralama maliyeti beraber ölçülür.

## Ünite 13: Bölümleme ve Veri Yaşam Döngüsü

Bölümleme sorgu budamasının yanı sıra veri yaşam döngüsünü yönetir. TTL politikaları eski veriyi sıcak depolamadan soğuk katmana ve sonunda silmeye taşıyabilir.

![Bölümleme TTL sıcak soğuk depolama animasyonu](https://alikoker.com.tr/svg/partition-ttl-hot-cold.svg "Bölümleme TTL ve sıcak soğuk depolama")


Bölüm, verinin bakım ve yaşam döngüsü açısından ayrılmasını sağlar; birincil indeksin yerini almaz. Aşırı yüksek kardinaliteli bölüm anahtarı her INSERT'in birçok küçük parça üretmesine neden olabilir. Zaman serisi tablolarında aylık veya günlük bölüm seçimi saklama süresi, veri hacmi ve toplu silme gereksinimine göre yapılır. TTL satır silme, taşıma, recompression veya belirli biçimlerde rollup için kullanılabilir; etkisi arka plan işlemlerine bağlıdır.

Bir tablo her gün 800 GB ham olay üretip ortalama 4:1 sıkıştırılıyorsa günlük sıkıştırılmış veri kabaca 200 GB olur. 90 günlük saklama süresi yaklaşık 18 TB aktif mantıksal veri verir. İki replica ile fiziksel veri kopyaları 36 TB'a çıkar; birleştirme geçici alanı, yedekler ve üstveri buna eklenir. Ay bazında bölüm seçimi, 90 günlük pencerede ay sınırlarına dokunan kalan günlerin TTL ile silinmesi gereğini ortadan kaldırmaz. Öte yandan günlük bölüm birkaç yüz milyonluk veri üzerinde uygun olabilir, ancak binlerce bağımsız tenant bölümü çarpanı tabloyu çok parçalı hale getirebilir. Bölüm seçimi veri hacmi ve düşürme granülerliğiyle belirlenir; sıralama anahtarı ile birlikte test edilmeden yalnız zaman filtresi kullanıldığı için her durumda gün seçilmez.

### 13.1. PARTITION BY ve Bölümleme Kardinalitesi

`PARTITION BY toYYYYMM(event_time)` ay bazında yönetim sağlar. Her müşteri veya olay kimliği için ayrı bölüm oluşturmak çoğu büyük veri kümesinde veri parçası sayısını yönetilemez hale getirebilir. Bölüm seçiminde yalnız SELECT filtresi değil insert dağılımı ve retention işlemleri değerlendirilir.

Bölüm, veriyi ayrı fiziksel gruplara ayırır; sıralama anahtarı bir bölüm içindeki satır düzenini belirler. Çok sayıda tenant veya yüksek kardinaliteli kimlik için doğrudan `PARTITION BY tenant_id` seçmek her tenant için ayrı veri parçası kümeleri oluşturacağından küçük veri parçası sayısını artırabilir. Zaman bazlı saklama gereksiniminde aylık bölüm, günlük veri hacmi ve silme sıklığı uygunsa yönetilebilir bir tercihtir; her tablo için otomatik doğru çözüm değildir.

Örneğin bir milyar olayın 12 aylık bölüme dağıldığı tabloda son 24 saat sorgusu, zaman filtresinin bölüm sınırlarına etkisine bağlı olarak en az içinde bulunulan ve gerekirse önceki ayın bölümünü ziyaret eder. Bölüm tek başına ay içerisindeki bütün kayıtları elemez; sıralama anahtarı ve granül düzeyli filtreleme gerekir. Benzer biçimde TTL ile satır seviyesinde silme, bölümün bir defada düşürülmesiyle eşit I/O maliyetine sahip değildir. Tam bölüm silme, hedef verinin bölüm sınırlarıyla eşleştiği durumlarda daha öngörülebilirdir.

### 13.2. Bölüm Budama ve Sıralama Anahtarı Ayrımı

Bölüm budaması koşulla ilgisiz bölümleri eler; sıralama anahtarı pruning kalan part'lardaki granül aralıklarını daraltır. Zaman üzerinden bölüm yapılması, tenant filtresini otomatik olarak hızlı kılmaz. İki mekanizmanın atladığı veri birimleri farklıdır.

Bölüm budaması, sorgu koşulunun bölüm ifadesini dışarıda bırakabildiği durumlarda tüm veri parçası ailelerini okumayı önler. Sıralama anahtarı budaması ise seçilen veri parçalarının içindeki işaret aralıklarını azaltır. `PARTITION BY toYYYYMM(event_time)` ile `ORDER BY (tenant_id, event_time)` birlikte kullanıldığında ay budaması ve tenant/zaman aralığı budaması farklı aşamalarda gerçekleşir. Bu iki düzenin ayrı işlevini karıştırmak, günlük bölüm oluşturma gibi gereksiz yüksek bölüm kardinalitesine yol açabilir.

### 13.3. Bölüm Kimlikleri, Parça Adlandırma ve Yönetim İşlemleri

Veri parçası adı bölüm kimliği ve parça dizisine ilişkin bilgi taşıyabilir; operasyonel otomasyon görünür ad kalıbına bağlanmamalıdır. `system.parts` üstverisi bölüm incelemesi için doğru sorgu yüzeyidir. Attach/detach işlemlerinde üstveri ve disk durumunun eşzamanlılığı önemlidir.

Bölüm kimliği, `PARTITION BY` ifadesinin sonucu ile ilişkilidir; veri parçası adı ve alanlarının anlamı sürüm ve depolama biçimine bağlıdır. Bir bölüm içindeki satırlar birleşebilir, farklı bölümler arası otomatik birleştirme beklenmemelidir. `ALTER TABLE ... DETACH PARTITION` gibi işlemler veri erişimini ve üstveri durumunu değiştirir; çalışma ortamında veri parçası dosyalarının nerede tutulduğu doğrulanmadan elle yeniden yerleştirilmemelidir. Büyük veri geri doldurmasında bölüm bazlı yükleme geri dönüşü kolaylaştırabilir.

Bir bölüm ay düzeyinde oluşturulmuş ve toplam 24 ay veri tutuluyorsa yönetim nesnelerinin sayısı öngörülebilirdir. Aynı tablo `PARTITION BY tenant_id` ile milyonlarca müşteri için bölünürse bir aylık 100 küçük INSERT'in her biri çok sayıda bölüme dağılıp aşırı sayıda veri parçası üretebilir. Bölüm seçimi, tek başına sorgu predikatları değil yazma bloklarının anahtar dağılımı ve TTL kaldırma birimiyle birlikte yapılmalıdır.

Veri parçası sayısı artışını sorgularken aktif ve inaktif parçalar ayrılmalıdır. İnaktif veri parçaları birleştirme sonrası geçici olarak diskte bulunabilir; bunları üretimde dosya sisteminden el ile kaldırmak hem hata toparlanmasını hem üstveri tutarlılığını tehlikeye atar. Operasyonel müdahalede `system.parts`, `system.part_log` ve uygun DDL işlemleri kullanılmalıdır.

### 13.4. TTL ile Silme, Taşıma, Yeniden Sıkıştırma ve Özetleme

TTL ifadesi kayıt yaşına göre silme veya belirli disk/volume'a taşıma tanımlayabilir. Satır düzeyinde TTL fiziksel temizliğin o anda tamamlandığı anlamına gelmez; birleştirme ve bakım döngüsü gecikme yaratabilir. Hukuki silme yükümlülüklerinde bu zaman farkı tasarlanmalıdır.

TTL kuralı veriyi yaşına göre silebilir, başka volume'a taşıyabilir veya yeniden sıkıştırabilir. Uygulama zamanı her satır için eşanlı fiziksel işlem anlamına gelmez; arka plan birleşmeleri ve bakım planlaması etkiler. Özellikle uyumluluk gerektiren silme taleplerinde sorgudan görünmezlik ile disk/backup üzerindeki bütün kopyaların temizlenmesi ayrı doğrulanır. Günlük retention hedefleri için bölüm düşürme ve satır seviyesinde TTL farklı maliyet modelleri sunar.

### 13.5. DROP PARTITION, DETACH, ATTACH ve TRUNCATE Farkları

`ALTER TABLE ... DROP PARTITION`, seçilen bölümün tabloya ait aktif verisini kaldıran yönetim işlemidir; satır düzeyinde `DELETE WHERE` ile aynı erişim ve geri alma semantiğini taşımaz. `DETACH PARTITION`, veri parçası dosyalarını `detached` alanına ayırarak sorgu görünürlüğünden çıkarır. `ATTACH PARTITION`, uygun detached veriyi tabloya yeniden ilişkilendirmek için kullanılır. `TRUNCATE TABLE` ise hedef tablonun veri içeriğini topluca temizler. Bu işlemler şema yapısını kaldıran `DROP TABLE` ile karıştırılmamalıdır.

```sql
SELECT partition, count() AS parts, sum(rows) AS rows
FROM system.parts
WHERE database = 'analytics' AND table = 'events' AND active
GROUP BY partition
ORDER BY partition;
```

Bu sorgu, herhangi bir yönetim işleminden önce gerçek bölüm kimliklerinin ve kapsamının belirlenmesini sağlar. Veri parçalarının `PARTITION BY` ifadesindeki bölüm değerleri, ham olay tarihinden farklı bir gösterime dönüştürülmüş olabilir. Sorgu sonuçlarındaki `partition` değeriyle hedeflenen DDL bölümünün eşleşmesi doğrulanmadan işlem yapılmamalıdır.

Örneğin günlük veri 90 gün saklanıyor, fakat fiziksel bölümler ay bazında oluşturuluyorsa `DROP PARTITION` ile tek bir günün verisi seçilemez; işlem bütün aya uygulanır. Bu durumda satır bazlı TTL ya da uygun silme işlemi gereklidir. `DETACH`, yedekleme politikası yerine geçmez: aynı disk arızasında detached dosyalar da kaybolabilir. ReplicatedMergeTree tablolarında bölüm işlemlerinin replikalara etkisi ve işlemin tamamlanma koşulları ayrıca izlenmelidir.

### 13.6. Disk ve Depolama Politikaları ile Sıcak–Soğuk Veri

Sıcak veri hızlı yerel diskte, az sorgulanan geçmiş uygun uzak depolamada bulunabilir. TTL MOVE ve depolama politikası bu yerleşimi yönetir. Uzak veri sık erişiliyorsa düşük depolama bedeli artan ağ ve önbellek maliyetini karşılamayabilir.

Sıcak veri için yerel hızlı disk, daha soğuk veri parçaları için nesne deposu kullanılabilir; ancak TTL MOVE politikası sorgu sırasında uzak veri erişiminin getirdiği gecikmeyi değiştirebilir. S3 gibi depolarda GET isteği sayısı, aktarılmış bayt ve ağ egress maliyeti önemlidir. Katman geçişini yalnız günlük yaşına göre belirlemek yerine sorgu sıcaklığı, veri parçası büyüklüğü ve kurtarma gereksinimi birlikte düşünülmelidir.

### 13.7. Zamana Dayalı Saklama ve Kapasite Tahmini

Sabit günlük hacim v_g ve saklama süresi d ise sıkıştırılmış veri için kaba kapasite C≈v_g×d olur. Birleştirme sırasında geçici kopyalar, yedekler, replikalar, üstveri ve büyüme payı ayrıca eklenir. Eski bölümün toplu düşürülmesi, çok sayıda satır DELETE'ine göre farklı maliyet sunabilir.

Retention hesabı gerçek sıkıştırılmış veri büyüklüğüyle karşılaştırılır:

```sql
SELECT
    database,
    table,
    sum(rows) AS rows,
    sum(data_compressed_bytes) AS compressed_bytes,
    sum(bytes_on_disk) AS bytes_on_disk
FROM system.parts
WHERE active
GROUP BY database, table
ORDER BY bytes_on_disk DESC;
```

İndeks ve üstveri dahil fiziksel alan için `bytes_on_disk`; kolon veri sıkıştırmasını ölçmek için `data_compressed_bytes` ayrı incelenir.

## Ünite 14: Arka Plan Birleştirmeleri ve Depolama İşlemleri

MergeTree yazma yolunda küçük değişmez partiler üretilebilir; arka plan birleştirmeleri bunları daha büyük sıralı partilere dönüştürür. Aşırı küçük partiler bu mekanizmayı darboğaza çevirebilir.

![Arka plan merge ve küçük partiler animasyonu](https://alikoker.com.tr/svg/background-merge-small-parts.svg "Arka plan birleştirmeleri ve küçük partiler")


Birleştirme işlemi, aynı partition'daki uyumlu data veri parçalarının sıralı akışlarını daha büyük bir veri parçası içinde birleştirir. İşlemin tamamı arka planda yürürken okuma eski aktif veri parçalarını kullanmaya devam edebilir; yeni parça hazırlandığında görünürlük değişir. Çok küçük INSERT'ler veri parçası sayısını ve background write amplification'ı artırır. Bu nedenle performans sorunu çoğu zaman SELECT optimizer'ından değil besleme granülerliğinden kaynaklanır.

Birleştirme sıklığını artırmak iki yönlü maliyet taşır. Küçük veri parçası sayısı azalınca SELECT planlaması ve dosya açma gideri düşebilir; fakat eşzamanlı birleştirme CPU ve disk I/O'nun bir bölümünü kaplar. Zorunlu `OPTIMIZE FINAL`, büyük veri parçalarını yeniden yazarak kısa vadeli sorgu performansı için geçici alan, network egress ve CPU maliyeti oluşturabilir. İyi tasarım, düzenli parti INSERT ve yeterli background birleştirme kapasitesiyle doğal dengeye ulaşmayı amaçlar. MergeTree ailesinin Replacing/Summing/Aggregating üyelerinde mantıksal dönüşümün birleştirme sırasında ortaya çıkması, iş uygulamasının doğru sorgu yazma sorumluluğunu kaldırmaz. `FINAL` ile birleştirme sonucunu okuma anında hesaplamak mümkün olduğunda bile p99 ve yoğun eşzamanlılık maliyeti ayrıca ölçülmelidir.

### 14.1. LSM Benzerliği ve MergeTree Farklılıkları

MergeTree veri parçası oluşturup arka planda birleştirdiği için LSM ailesiyle bazı özellikler paylaşır; fakat RocksDB'nin key-value seviye düzeniyle birebir aynı algoritma değildir. Veri parçası seçim politikası, sıralama anahtarı ve sütun yönelimli storage farkları önemlidir.

MergeTree'nin yeni yazıları ayrı sıralı veri parçalarına alıp arka planda birleştirmesi LSM-tree ailesiyle yapısal benzerlik taşır. Bununla birlikte ClickHouse veri parçalarını sütunlu dosyalar, sparse işaret indeksleri ve analitik taramaya uygun veri kodlaması içerir; klasik anahtar–değer LSM uygulamasıyla aynı okuma/yazma davranışını sunmaz. Noktasal güncelleme oranı ve zaman serisi append iş yükü tasarımı belirgin biçimde etkiler. “LSM benzeri” ifadesi mimari akrabalığı açıklar, tam motor eşdeğerliği değil.

### 14.2. Birleştirme Seçimi, Parça Düzeyleri ve Eşzamanlılık

Birleştirme için parça seçimi veri parçası boyutu, yaş, disk alanı, küme baskısı ve tablo ayarlarıyla ilişkilidir. Veri parçasının birleştirme düzeyi fiziksel geçmiş hakkında fikir verir; her düzey için tek bir kesin boyut garantisi yoktur. Arka plan işçileri ve disk aktarım kapasitesi de kapasite planına dahildir.

Birleştirme seçiminde veri parçası boyutları, bölüm, birleştirme havuzu kaynakları ve eşzamanlı yürüyen görevler önemlidir. Çok küçük veri parçalarının sürekli eklenmesi seçim algoritmasının verimli büyük birleşmelere ilerlemesini engelleyebilir. Birleştirme düzey tek başına veri dosyasının sorgu değeri veya kesin fiziksel yaşını göstermez. Verimli bir birleştirme planı, yazma amplifikasyonu ile sorguda okunacak veri parçası sayısı arasında maliyet dengesi kurar.

Birleştirme planlayıcısı için hedef her veri parçasını hemen tek bir büyük dosyaya dönüştürmek değildir. Veri parçası boyutları eşit olmayan kümelerde büyük bir veri parçasının küçük part'larla sık sık yeniden yazılması aşırı yazma amplifikasyonu doğurur. Gelen veri hızı 300 MB/s, birleştirmelerin sürekli yazabildiği hız 200 MB/s ise ilk bakışta fark 100 MB/s görünür; fakat kaynak veri parçaları da okunduğu ve aynı satır birden çok kez yazılabildiği için yalnız giriş-çıkış baytından kararlılık sonucu çıkarılamaz. Gerçek tanılama, birleştirme kuyruğunun yaşını, etkin veri parçası sayısını, sıkıştırılmış yazılan baytı ve disk meşguliyetini birlikte izler.

Veri parçası sayısı aynı kalırken toplam parça boyutunun ve birleştirme süresinin büyümesi farklı bir rejimdir. Özellikle yüksek kardinaliteli bölüm anahtarları birbirinden bağımsız küçük parça kümeleri üretir. Bu durumda `OPTIMIZE FINAL` çağrısının tek seferlik başarısı kapasite sorununu çözmüş sayılmaz.

### 14.3. Yazma Amplifikasyonu ve Küçük Parça Sorunu

Günde 10⁶ tek satırlık INSERT ile aynı verinin 10⁴ satırlık 100 parti olarak yazılması aynı toplam satır sayısına rağmen çok farklı veri parçası sayısı doğurur. Yazma büyütmesi, bir bayt verinin birleşmeler sırasında kaç kez yeniden yazıldığıyla ilişkilidir; küçük veri parçası sayısındaki artış bu maliyeti yükseltir.

INSERT stratejisinin tabloya etkisini görmek için 1.000.000 olayın 1000 satırlık batch'lere ayrılması ile 100.000 satırlık batch'lere ayrılması karşılaştırılır. İlk yaklaşım yaklaşık 1000, ikincisi yaklaşık 10 yeni veri parçası oluşumuna yol açabilir; kesin sayı INSERT blokları, bölüm çeşitliliği ve async flush davranışına bağlıdır. Veri parçası sayısı tek başına amaç değil, birleştirme havuzunun sürekli biriken işi karşılayabilmesidir. Sürekli düşük gecikmeli trafik varsa istemcide parti gecikmesi ile sunucu yazım ekonomisi arasında kontrol edilen bir tamponlama penceresi kurulur.

Bir INSERT'in birden fazla veri parçası üretmesi, arka plan birleştirme işlemlerinin iş yükünü doğrudan artırır. `r` saniyede oluşan veri parçası sayısı, `m` birim zamanda birleştirme işlemleriyle sistemden eksilen net veri parçası sayısı ve `P(t)` aktif veri parçası sayısı olsun. Basit kuyruk modeli `dP/dt ≈ r-m` biçimindedir. `r>m` durumu kalıcıysa veri parçası sayısı artar; disk, dosya tanıtıcıları, üstveri belleği ve sorgu planlama maliyeti büyür. Gerçekte birleştirme görevleri birden çok girdiyi tek çıktıya dönüştürdüğünden `m`, çalışan birleştirme sayısıyla aynı değildir.

Yazma büyütmesi, depoya gelen bir bayt veriye karşılık arka planda tekrar yazılan toplam baytın oranıdır. Bir veri parçası daha büyük seviyelere birden fazla kez katıldıkça aynı veri fiziksel olarak yeniden yazılabilir. Sık INSERT, yalnız istemci çağrısı maliyeti değil arka plan disk ve CPU bütçesi de tüketir. `OPTIMIZE FINAL`, birleştirme politikasını zorlayarak büyük veri parçası oluşumuna ve uzun süreli kaynak kullanımına neden olabileceğinden genel bakım refleksi haline getirilmez.

Veri parçası birikimi `system.parts` üzerinde aktif veri parçası sayısı, bölüm bazlı dağılım ve ortalama veri parçası boyutuyla; `system.merges` üzerinden çalışan birleşmelerle birlikte değerlendirilir. Yalnız tek bir anda `system.merges` tablosunun boş olması normal davranış da olabilir; bir zaman serisi ve INSERT hızı olmadan arıza sonucu çıkarılamaz.

Veri parçası ekonomisi basit bir kararlılık problemi olarak modellenebilir. Saniyede λ veri parçası oluşturuluyor ve arka plan birleşmeleri saniyede ortalama μ veri parçası eksiltiyorsa kalıcı yük altında `λ ≥ μ` durumunda aktif veri parçası sayısı artar; birleşme işi tek bir merge'de birkaç veri parçasını tükettiğinden μ hesabı net azalma olarak yapılmalıdır. Sürekli küçük INSERT'lerde ağ ve SQL overhead'ine ek olarak yeni dosyalar, işaret dosyaları, üstveri ve Keeper koordinasyonu çoğalabilir.

İlk tanılama, veri parçası sayısı ile yaş dağılımını aynı anda okumaktır. Az sayıda büyük veri parçasının varlığı her zaman iyi sorgu sonucuna işaret etmediği gibi, çok sayıda küçük veri parçası doğrudan disk doluluğu belirtisi değildir; uzun süre kalıcı veri parçası üretim hızı baskınsa merging kuyrukları ve replikasyon gecikmeleri birlikte yükselir. Üretimde başlıca müdahale, toplu yazmayı ve asenkron INSERT tamponlamasını düzeltmektir; sık `OPTIMIZE FINAL` çalıştırmak kaynak tüketimini büyütebilir.

### 14.4. Arka Plan Birleştirmeleri ve Bellek Yönetimi

Background birleştirme CPU, bellek ve disk bant genişliği tüketir. Sorgu gecikmesiyle yarışabilir; geniş veri parçalarını birleştirmek geçici boş alan da ister. Bellek-optimize birleştirme yollarının tüm koşullarda etkin olduğu varsayılmamalı; `system.merges` üzerinden gerçek davranış gözlenmelidir.

Arka plan birleşmesinin girdisi olan veri parçalarının toplam boyutu, geçici disk ve ardışık okuma/yazma tüketimi yaratır. Aynı anda çok sayıda büyük birleştirme başlatmak sorgu iş yükünün disk bant genişliğini azaltabilir. Birleşmenin tamamlanmasından önce yeni veri parçasının görünür olması ile eski veri parçalarının kaldırılması üstveri koordinasyonu gerektirir. Birleşme kuyruğunun sürekli büyümesi, INSERT hızının sürdürülebilir birleştirme kapasitesini aştığını veya veri parçası dağılımının dengesiz olduğunu gösterebilir.

### 14.5. OPTIMIZE FINAL Maliyeti ve Güvenli Kullanım

`OPTIMIZE TABLE ... FINAL` büyük miktarda verinin zorunlu yeniden yazımına yol açabilir; bu nedenle sıradan bakım komutu olarak periyodik çalıştırılması önerilmez. Doğru INSERT stratejisi ve doğal birleştirme akışı birincil çözümdür. FINAL sorgu değiştiricisiyle OPTIMIZE FINAL aynı işlem değildir.

`OPTIMIZE TABLE ... FINAL` veri parçalarını zorla birleştirmeye çalışabilir; bunun büyük veri kümelerinde yüksek disk I/O, CPU ve geçici alan maliyeti vardır. Normal arka plan birleşmesiyle farklı bir bakım semantiği sunduğundan periyodik ve kontrolsüz çalıştırılması uygun değildir. ReplacingMergeTree doğruluğunu bu komuta bağımlı kurmak da hatalıdır; sorgu anı `FINAL` veya uygun toplulaştırma semantiği ayrıca kullanılabilir. Karar veri parçası sayısı ve hedef sorgu üzerinden verilmelidir.

### 14.6. Birleştirme Sırasında Toplulaştırma, Tekilleştirme ve Dönüşüm

ReplacingMergeTree, SummingMergeTree ve AggregatingMergeTree birleştirme sırasında motorlarına özgü dönüştürmeler yapabilir. Merge'ün gerçekleşme zamanı sabit olmadığından sorgu doğruluğu yalnız arka plan işleminin bitmiş olmasına dayandırılmaz. Versiyon veya aggregate-state semantiği sorguyla tamamlanmalıdır.

`SummingMergeTree` ve `AggregatingMergeTree`, birleşme sırasında satırları özetleyebilir; `ReplacingMergeTree` anahtar ve sürüm kurallarına göre satırları azaltabilir. Bu dönüşümler hemen INSERT anında tamamlanmış sayılmaz. Aynı mantıksal anahtara ilişkin birden çok veri parçası olduğunda sorgu gerektiğinde birleştirme semantiğini ayrıca uygulamalıdır. Arka plan birleştirmesinin sonucu sorgu doğruluğunun tek koşulu haline getirilirse, aynı veritabanı farklı anlarda farklı nihai görünen sonuçlar üretebilir.

Birleştirme sırasında deduplication deterministik bir çevrimiçi tekillik kısıtı değildir. Örneğin aynı `(tenant_id, event_id)` anahtarının sürüm 3 ve sürüm 5 kayıtları ayrı part'larda bulunabilir; arka plan birleştirme tamamlanmadan sorgu ikisini de görebilir. `ReplacingMergeTree(version)` için en yüksek sürümün seçilmesi gerekir; eşit sürümlerde hangi kaydın korunacağına iş kuralları açısından belirsizlik taşımamak için benzersiz ve monoton sürüm üretimi tercih edilir.

`SummingMergeTree` için toplama kapsamına giren alanlar ve anahtarın boyutu birlikte tasarlanır. Bir olayı her CDC tesliminde yeniden eklemek, olayı iki kez sayma riski yaratır; birleştirme işlemi tek başına CDC çoğaltmasını ortadan kaldırmaz. `AggregatingMergeTree` üzerinde `countState()` veya `uniqState()` gibi durumlar kullanılıyorsa sonuçlar `countMerge()` ya da `uniqMerge()` ile okunmalıdır. Birleştirme semantiği, veri alımındaki idempotency politikasından bağımsız düşünülemez.

### 14.7. System.merges ve Veri Parçası Birikiminin Analizi

`system.merges` aktif birleştirme işlemlerini, `system.parts` aktif parça dağılımını gösterir. Küçük veri parçaları sürekli birikiyor ve birleştirme havuzu doygunsa önce INSERT miktarı, bölüm kardinalitesi ve depolama darboğazı incelenir; kör biçimde thread sayısı artırılmaz.

Aktif birleştirmelerin görünür durumu:

```sql
SELECT
    database,
    table,
    elapsed,
    progress,
    num_parts,
    formatReadableSize(total_size_bytes_compressed) AS total_compressed
FROM system.merges
ORDER BY elapsed DESC;
```

Bu sorgunun boş sonuç döndürmesi birleşme maliyeti yaşanmadığı anlamına gelmez; örnekleme anında etkin görev yoktur.

`system.merges` çalışan birleşmeleri, `system.parts` kalan aktif parçaları, `system.part_log` ise veri parçası olaylarının geçmişini gösterebilir. İzlemede veri parçası sayısını tek başına eşiklemek yanıltıcıdır: toplam veri hacmi, bölüm sayısı, ortalama veri parçası boyutu, işlem süresi ve bekleyen veri hacmi birlikte değerlendirilir. Sorgu gecikmesi yükselirken birleştirme CPU/I/O tüketimi de artıyorsa iki iş yükü arasında kaynak çakışması olup olmadığı sınanır.

## Ünite 15: MergeTree Tablo Motorları ve Birleştirme Semantiği

ReplacingMergeTree aynı anahtarın birden fazla sürümünü fiziksel olarak birlikte taşıyabilir. En güncel sürümün görünmesi merge zamanlaması ve okuma semantiğiyle ilişkilidir.

![ReplacingMergeTree sürüm birleştirme animasyonu](https://alikoker.com.tr/svg/replacing-mergetree-version-merge.svg "ReplacingMergeTree sürüm semantiği")


MergeTree motor ailesi depolama ve birleştirme sırasında uygulanan semantiği değiştirir; hiçbir motor seçimi kaynak veri modelini otomatik olarak doğru hale getirmez. ReplacingMergeTree aynı sıralama anahtarına sahip farklı sürümleri birleştirme sırasında azaltabilir, ancak birleştirme tamamlanmadan birden çok fiziksel sürüm bulunabilir. SummingMergeTree ve AggregatingMergeTree belirli agregasyon yapılarını depolama düzeyinde destekler. Hangi motorun kullanılacağı sorguların beklediği tutarlılık ile veri akışının değişim modeline bağlıdır.

ReplacingMergeTree'de aynı sıralama anahtarına sahip iki fiziksel kayıt, birleştirme tamamlanana kadar ayrı satırlardır. `FINAL` eski sürümlerin okuma anındaki görünürlüğünü etkileyebilir; fakat yanlış kimlik seçimini düzeltmez. Bir CDC kaynağında aynı hedef numarası farklı iş olayları için tekrarlanabiliyorsa bu alanı tek başına sıralama anahtarı olarak kullanmak veri kaybına benzer mantıksal sonuç doğurabilir. İdeal anahtar mevcut iş modelindeki kalıcı kimliğe dayanmalıdır; böyle bir kimlik yoksa onun yokluğu açıkça yönetilmelidir. SummingMergeTree'nin toplayacağı alanın toplamlanabilir olması; Averaging/quantile gibi ölçülerin uygun agregasyon durumuyla saklanması gerekir. Bu ayrımlar olmadan seçilen tablo motorunun yazma maliyetini azaltması rapor doğruluğunu garanti etmez.

### 15.1. MergeTree ve ReplicatedMergeTree

MergeTree tek düğümde sütun veri parçaları saklar; ReplicatedMergeTree replikalar arasında veri parçaları ve üstveri koordinasyonu sağlar. Replikasyon yedekleme değildir ve bir replica düşse bile kaynak verinin bozulması diğer replikalara yansıyabilir. Replica sayısı ve bölüt sayısı farklı ölçekleme boyutlarıdır.

MergeTree tabloya gelen veriyi sorted veri parçalarına yazar ve arka plan birleştirme işlemlerini yönetir. ReplicatedMergeTree aynı temel veri yapısını Keeper koordinasyonu ve replica veri parçası kopyalama mekanizmasıyla genişletir. Aynı verinin iki replica'da tutulması, her sorgunun iki kat hızlı olması anlamına gelmez; aynı bölüt için farklı okuma isteklerinin replica'lara dağıtılması mümkündür. Replica konumu ve işlem onayı/tazelik beklentisi tutarlılık tasarımının parçasıdır.

### 15.2. ReplacingMergeTree: Sürüm, Silme İşareti ve FINAL

`ReplacingMergeTree` aynı `ORDER BY` anahtarı için birden fazla fiziksel sürüm barındırabilir. Arka plan birleştirmesi sırasında sürüm sütunu varsa en büyük sürüm korunur. Bu davranış `PRIMARY KEY` üzerinde benzersizlik kısıtı uygulamaz; INSERT anında aynı anahtarın ikinci kez yazılması engellenmez. `FINAL`, okuyucunun birleştirme henüz tamamlanmadan mantıksal sürüm seçimi yapmasına imkan verir ve sorgu maliyetini artırabilir.

Kaynak kayıtlarından gelen güncelleme ve silme olaylarının aynı biçimde ifade edilebilmesi için sürüm ve silme göstergesi birlikte tanımlanır:

```sql
CREATE TABLE latest_states
(
    record_id UInt64,
    version UInt64,
    deleted UInt8,
    state String
)
ENGINE = ReplacingMergeTree(version, deleted)
ORDER BY record_id;

INSERT INTO latest_states VALUES
(7, 1, 0, 'OPEN'),
(7, 2, 0, 'CLOSED'),
(8, 1, 0, 'ACTIVE'),
(7, 3, 1, '');

SELECT record_id, state
FROM latest_states FINAL
WHERE deleted = 0
ORDER BY record_id;
```

Yukarıdaki mantıksal görünümde `record_id=7` için en yüksek sürüm bir silme işaretidir; `record_id=8` ise etkin kayıttır. Silme işaretinin motor parametresine verilmesi, tek başına eski fiziksel baytların hemen imha edildiği anlamına gelmez. Silme işaretlerinin saklanması, temizlenmesi ve sonradan gelebilecek eski sürümlere karşı davranışı işletim politikasıyla belirlenir.

Tekilleştirme anahtarı `record_id` değil, **tam `ORDER BY` ifadesidir**. Anahtar `(record_id, event_time)` olarak seçilirse aynı kimliğin farklı olay zamanlarında oluşan sürümleri farklı gruplara ayrılır. Farklı partition'larda tutulan aynı mantıksal anahtarın birleştirilme davranışı da arka plan birleştirme işlemlerinin bölüm sınırlarına bağlıdır. Yanlış bölütleme veya birden fazla bölüte dağıtılan aynı kimlikler için tek düğümde `FINAL` kullanılması küresel doğruluk garantisi oluşturmaz.

Kaynak sürüm numaralarının monoton artması gerekir. Aynı anahtar ve aynı sürümle çelişkili içerik aktarılırsa seçimin deterministikliği bu örnek şemada iş kuralıyla güvence altına alınmış değildir. `WHERE deleted=0` koşulunun yanlış bir alt sorgu veya ön filtre içinde eski sürümleri seçmeden önce uygulanması, silinmiş kayıtların yeniden görünmesine yol açabilir. CDC mutabakatı kaynak anahtar–sürüm–silme işareti üçlüsü üzerinden kurulmalıdır. [8]

### 15.3. SummingMergeTree ve AggregatingMergeTree

`SummingMergeTree` aynı sıralama anahtarı altındaki sayısal alanları birleşme sırasında toplayabilir; anahtarın semantiği yanlış kurulursa farklı olaylar geri döndürülemez biçimde aynı özete taşınır. `AggregatingMergeTree` sayısal sonuç yerine birleşebilir agregasyon durumlarını saklar. Örneğin `avgState(x)` için toplam ve sayaç bilgisi tutularak `avgMerge` ile doğru birleşim yapılabilir. İki önceden hesaplanmış ortalamayı doğrudan toplamak veya ortalamasını almak genel durumda doğru değildir.

Özet durumlarının fiziksel tipleri de önemlidir. `AggregateFunction(avg, Float64)` tipindeki alan bir `Float64` sonuç sütunu değildir; birleştirme için gerekli ara bilgiyi taşır. `SimpleAggregateFunction` ise desteklenen fonksiyonlarda sonuç türünü daha doğrudan saklayabilir. Bunları veri tipi ve birleştirme işlemleri bakımından eşdeğer kabul etmek, özellikle sürüm yükseltmelerinde uyumsuz şema üretir.

Günlük ortalama gecikmelerin haftalık ortalamasını hesaplarken günlük olay sayıları farklıysa `avgMerge` durumlarının birleştirilmesi gerekir. Yedi günlük ortalamayı aritmetik olarak ortalamak yalnız her gün aynı sayıda olay bulunduğunda eşdeğerdir. İstatistiksel veri ürünlerinde saklanan özetin matematiksel olarak yeniden birleştirilebilir olup olmadığı, sorgu maliyetinden önce doğrulanmalıdır.

### 15.4. CollapsingMergeTree ve VersionedCollapsingMergeTree

CollapsingMergeTree işaret sütununu, VersionedCollapsingMergeTree sürümle ilişkili dengeleme mantığını kullanır. İşaret olaylarının eksik veya yanlış sırayla gelmesi veriyi yorumlamayı zorlaştırabilir. CDC olayları doğrudan bu motorlara bağlanmadan önce tanımlı test dizileriyle doğrulanmalıdır.

`CollapsingMergeTree` işaret (`Sign`) değerini kullanarak eşleşen durumları birleşme sırasında karşılıklı düşürebilir. `VersionedCollapsingMergeTree` sürüm alanını dikkate alan daha belirli bir olay sıralama modeli sunar. Bu motorlarda işaretlerin eksik veya yinelenmiş gelmesi hesaplanan sonucun bozulmasına yol açabilir; CDC kaynağındaki delete/update olaylarının aktarımı bu nedenle doğruluk açısından kritik önemdedir. Arka plan merge'lerinin tamamlanması beklenmeden sorgu yapılacaksa sorgu agregasyonunun collapse semantiğiyle uyumlu olması gerekir.

### 15.5. AggregateFunction ve SimpleAggregateFunction Durumları

`AggregateFunction(sum, UInt64)` bir agregasyonun iç durumunu saklar; `SimpleAggregateFunction` daha kısıtlı, sonuç türüne eşit temsil edilebilen işlemler için uygundur. Agregasyon durumlarının binary biçimi dış sistemlerle kalıcı protokol gibi paylaşılmamalı; tablo sürümü ve fonksiyon uyumluluğu korunmalıdır.

`AggregateFunction` fiziksel olarak birleştirilebilir agregasyon durumunu, `SimpleAggregateFunction` ise tanımlı basit birleşme semantiği bulunan nihai tipli bir değeri saklar. `uniqState` gibi eskiz durumlarının bayt dizisi doğrudan nihai sayı olarak yorumlanamaz. Doğru eşleştirme `...State` yazma, `...Merge` okuma biçimindedir; bazen `finalizeAggregation` kullanılabilir. Durum biçimlerinin sürüm ve uyumluluk gereksinimleri yedekleme ve dışa aktarma sırasında göz önünde bulundurulmalıdır.

### 15.6. Tekilleştirme Doğruluğu ve Birleştirme Gecikmesi

Insert deduplication aynı insert bloğunun yeniden denenmesini sınırlayabilir; iş anlamında aynı olayın farklı bloklarla gelmesini otomatik engellemez. Background birleştirme zamanı deterministik olmadığı için `COUNT(*)` gibi saf satır sayımı ReplacingMergeTree'de aynı kimliğin birden çok sürümünü sayabilir.

ClickHouse'un `INSERT` tekilleştirmesi, uygulama düzeyindeki bütün mantıksal olayları global olarak tekilleştirme garantisi değildir. Tekilleştirme token'ı, veri bloğu kimliği veya ReplacingMergeTree sorting key'i farklı kapsamlarda çalışır. İki aynı mantıksal olay farklı anahtarlarla gelirse `FINAL` bunları kendiliğinden birleştirmez. Tam veri doğruluğu için kaynak olay kimliği, CDC tekrar oynatma davranışı, şema versiyonu ve hedef sorgu semantiği birlikte tanımlanmalıdır.

### 15.7. Sürüm Bazlı Güncelleme ve Doğru Sonuç Okuması

Versiyonlanmış olay kayıtları için `(kimlik, sürüm, deleted)` sözleşmesi ve en yüksek sürüm kuralı belirlenir. Düzeltme ve silme sonrasında en güncel mantıksal durumun okunması `FINAL`, argMax, uygun MV veya başka bir sorgu tasarımı gerektirebilir. Performans ve doğruluk birlikte ölçülür.

Sürüm bazlı veri modelinde aynı sıralama anahtarı altında daha yüksek sürüm seçilmesi güncel görünümü üretir; sıralama anahtarı olay kimliğini yanlış temsil ediyorsa farklı mantıksal kayıtlar birleşebilir. ReplacingMergeTree'de fiziksel birleştirmelerin zamanlaması deterministik kabul edilemez. `FINAL` ile sorgu semantiği tamamlanabilir, ancak geniş taramalarda ek hesaplama maliyeti doğurabilir. Sürümün kaynaktan gelen monoton işlem konumuyla ilişkilendirilmesi, gecikmeli CDC olaylarının eski veriyi yeniden güncel göstermesini engellemeye yardımcı olur.

## Ünite 16: Diğer Tablo Motorları ve Harici Veri Kaynakları

ClickHouse tablo motoru, verinin nerede ve nasıl tutulacağını veya hangi dış veri kaynağına bağlanılacağını belirler. Her motor MergeTree ailesiyle aynı dayanıklılık, indeksleme ve mutation garantilerini sunmaz. Harici veri bağlayıcıları kaynak sistemin kimlik doğrulama, ağ ve şema semantics'ine bağımlıdır. Bu nedenle motor seçimi yalnız CREATE TABLE sözdizimi değil işletim ve arıza modelidir.

Harici motorun verdiği SQL arayüzü, veri kaynağının erişim modelini değiştirmez. PostgreSQL motoruyla yapılan dış SELECT, kaynak PostgreSQL üzerinde CPU, connection ve I/O tüketir; büyük join'i ClickHouse tarafında mı kaynakta mı yürütüleceği planlamaya bağlıdır. Aynı tablo yerel MergeTree'ye alınırsa veri tazeliği ve replikasyon maliyeti ortaya çıkar. `Kafka` motoruyla topic tüketimi kalıcı bir veritabanı tablosu oluşturmayabilir; olaylar hedef MergeTree'ye aktarılacaksa MV ve offset sözleşmesi gerekir. `Memory` veya Tampon motorlarının hızlı görünmesi bunların kritik kalıcılık koşullarını sağladığı anlamına gelmez. Motor seçimiyle depolama katmanının veri kaybı modeli de seçilmiş olur.

### 16.1. Memory, Log, TinyLog, StripeLog, Tampon

`Memory`, `Log`, `TinyLog`, `StripeLog` ve `Buffer` motorlarının amaçları MergeTree'den farklıdır. `Memory` veri satırlarını RAM'de tutar; süreç yeniden başladığında kalıcılık beklentisi bulunmayan geçici hesaplamalarda kullanılabilir. Log ailesi, basit dosya yerleşimi sunar fakat MergeTree'nin sıralı veri parçası, seyrek birincil indeks, TTL ve arka plan birleştirme tasarımının yerine geçmez. Log motorlarının dosya düzeni ve eşzamanlı okuma/yazma özellikleri aynı kabul edilmemelidir.

`Buffer` motoru, hedef tabloya iletilecek veriyi arabellekte biriktirmek için tasarlanmıştır. Tampon boşaltılmadan yaşanan arızalar veri kaybı riskini artırabilir; bu nedenle olayların tek gerçek kaynağı olarak ele alınmaz. Modern küçük INSERT iş yüklerinde, MergeTree hedefine `async_insert` kullanılarak sunucu tarafında toplu yazım oluşturulması daha doğrudan bir seçenektir. Ancak yazma onayı için `wait_for_async_insert` davranışı ayrıca değerlendirilmelidir.

Motor seçimi dört değişkenle yapılır: yeniden başlatma sonrasında kalıcılık, beklenen yazma hacmi, sorgu erişim örüntüsü ve gerekli kurtarma seviyesi. `Memory` kullanımının düşük disk maliyeti, kalıcı depolama isteyen uygulamalarda avantaj değildir. `Log` ailesinin az sayıda dosya kullanması da geniş zaman aralıklı OLAP filtrelerinde fiziksel indeksin yokluğunu telafi etmez.

`FileLog`, bir dosya yolunu izleyerek eklenen günlük verilerini okumaya yöneliktir; MergeTree üzerinde kalıcı, analitik sorgu için optimize edilmiş bir tablonun yerini tutmaz. Dosya döndürme, yeniden başlatma, okuma konumu ve yeniden işleme semantiği özel olarak değerlendirilir. ClickHouse 26.10'da FileLog'un dosya döndürme desteği geliştirilmiş, `SYSTEM RESET FILELOG` ile belirli bir dosyanın okuma konumunun ayarlanmasına yönelik seçenekler sunulmuştur. Yeniden oynatma hem eksik hem tekrar kayıt riski taşıyabilir; üretimde hedef olay kimliği ve tüketilen konum birlikte doğrulanmalıdır. Dosya temelli takip, şema doğrulaması, uzun süreli saklama ve analitik sorgu için MergeTree'ye aktarımla tamamlanabilir. [41]

### 16.2. Distributed, Birleştirme, Dictionary ve Set

Distributed motor sorguyu bölütlere yönlendirir; yerel veri parçaları'ları kendisi depolayan MergeTree değildir. Birleştirme motoru birden çok tabloyu mantıksal birleştirebilir; Dictionary ve Set belirli erişim örüntülerini karşılar. Dağıtık agregasyonun doğru sonuç için hangi alanlarda global aşama gerektirdiği incelenir.

Distributed motoru kümedeki uzak tabloları mantıksal sorgu arabiriminde toplarken Birleştirme motoru aynı sunucudaki uygun tablolar üzerinde sorgu çalıştırabilir. Dictionary özel lookup düzeni, Set ise belirli üyelik denetimlerinde yararlanılabilecek yapı sunar. Bu motorların fiziksel satır saklaması ve arka plan bakım davranışı birbirinin aynı değildir. Dış arayüzün tek tablo gibi görünmesi, hepsinin aynı veri kalıcılığına sahip olduğu anlamına gelmez.

### 16.3. Kafka, MySQL, PostgreSQL, JDBC, URL

Kafka motoru akıştan veri tüketimi için bir entegrasyon girişidir; MySQL/PostgreSQL/JDBC gibi motorlar dış sistemlerle sorgu ve veri alışverişi sağlar. Gecikme ve işlem garantileri veri kaynağına ve aradaki sürücüye bağlıdır. Bu bağlantılar genel amaçlı iki yönlü işlem replikasyonu anlamına gelmez.

Kafka motoru akıştaki mesajların alınmasına yönelik bir giriş katmanı olabilir; çoğunlukla materyalleştirilmiş görünüm ile kalıcı MergeTree tablosuna aktarım yapılır. MySQL/PostgreSQL ve JDBC bağlantıları kaynak tabloya uzaktan erişim veya veri içe aktarma amaçlarıyla kullanılabilir. URL motoru ve fonksiyonlar ağdan okuma/yazma yapabildiğinden yetki, veri biçimi ve transfer maliyeti denetlenmelidir. Kaynağın SQL semantiği ClickHouse motoruna otomatik olarak taşınmaz.

### 16.4. S3, HDFS, File ve Tablo Fonksiyonları

S3, HDFS ve File işlevleri Parquet/CSV gibi dosyalara SQL erişimi sağlar. S3 üzerinde sık SELECT, her çağrıda ağ ve object-store üstveri maliyeti doğurabilir; yerel MergeTree index/ordering yeteneklerinin varlığı varsayılmaz. Yükleme mi harici okuma mı kararı iş yüküyle verilir.

S3 ve HDFS gibi uzak kaynaklarda Parquet/CSV dosyaları doğrudan analiz edilebilir; `file` işlevleri yerel dosyalarda yararlıdır. Tablo fonksiyonları ad-hoc veri incelemesinde uygunken sık ve yüksek hacimli sorgulamada kalıcı MergeTree tabloya yükleme avantaj sağlayabilir. Nesne sayısı çok fazlaysa listeleme ve dosya açma maliyeti, gerçek veriyi okumadan önce gecikme oluşturur. Parquet row-group istatistikleri ile MergeTree sparse primary index'i aynı budama katmanı değildir.

ClickHouse 26.10'daki SQLite dışa aktarma/içe alma formatı, daha önce mevcut olan SQLite veritabanı motoru veya `sqlite` tablo fonksiyonundan farklı bir yetenektir. Bir sonuç kümesinin tek SQLite dosyası olarak aktarılması, verinin başka araçlarla paylaşılmasını kolaylaştırır; işlem garantisi ve indeks düzeni çıktı dosyasının biçimine tabidir. Dosya üzerinden yeniden okuma sırasında metin/tarih türleri, NULL ve sayısal hassasiyetin korunması, örnek veriyle değil uç durumlarla doğrulanmalıdır. Bu yöntemin dağıtık ClickHouse kümesi için yeni bir işlem deposu oluşturmadığı açıktır. [41]

### 16.5. Harici Kaynaklar, Motor Seçimi ve Sınırlar

Bir motorun kurulumunun kolay olması başarım ve operasyon uygunluğunu kanıtlamaz. Veri kaynağı kimliği, zaman aşımı, geri basınç, şema mapping, yeniden oynatma ve hata sonrası devam protokolleri ayrı sorumluluklardır.

Dış kaynak motorlarının tamamı MergeTree'nin veri parçası, indeks veya birleştirme özelliklerini otomatik olarak miras almaz. JDBC ya da uzak SQL motoru üzerinden sorgulamada hangi filtrelerin kaynağa itildiği ve hangi işlemlerin ClickHouse üzerinde yapıldığı ayırt edilmelidir. Büyük bir tablonun tamamı ağ üzerinden çekiliyorsa kaynak tarafındaki indeksler kullanılsa bile toplama planı pahalı olabilir. Entegrasyon motoru seçimi yalnız bağlantı mümkünlüğüne değil, erişim semantiğine ve veri doğruluğuna dayanmalıdır.

26.10 sürümünde `Cluster` ve `Overlay` veritabanı motorları farklı tabloların birleştirilmesi veya federasyonu için ek seçenekler sunar. Birleşik ad alanı, dağıtık işlem ya da tekil doğruluk kaynağı sağlamaz; adlandırma, yetki ve şema çakışmalarının yönetimi gerekir. Aynı sürümde duyurulan deneysel Elasticsearch tablo motoru, bir Elasticsearch indeksindeki belgelerin ClickHouse SQL ile okunmasını amaçlar. Kaynak tarafındaki arama/indeks davranışı değişmez; motor, Elasticsearch'ü MergeTree'ye dönüştürmez. [41]

`chDB`, ClickHouse yürütme motorunun Python uygulaması içerisinde sunucusuz kullanılabilen gömülü biçimidir. Parquet gibi dosyaları ve DataFrame nesnelerini işlem içinde sorgulayabilir; böylece yerel bir analitik görevde ağ turu ve bağımsız ClickHouse sunucusu işletme gereksinimi ortadan kalkar. Bunun karşılığında işlem belleği, eşzamanlılık, süreç çökmesi, çok kullanıcılı erişim ve kalıcılık sınırları gömülü uygulamanın yaşam döngüsüne bağlanır. Merkezi, çok düğümlü ClickHouse kümesinin replikasyon ve yetki modelinin chDB tarafından otomatik sağlandığı varsayılamaz. DuckDB karşılaştırmasında aynı yerel veri, işlem sayısı ve veri alışverişi maliyetleri kullanılmalıdır. [47]

### 16.6. Tampon, Disk ve Önbellek Davranışı

Tampon, native önbellek ve işletim sistemi sayfa önbelleği birbirinden farklıdır. Bir ara katman eklemek kaynak verinin kalıcılığını güçlendirmeyebilir; aksine görünürlük ve kayıp penceresi yaratabilir. Her önbellek için invalidation ve tutarlılık sözleşmesi gerekir.

Memory motoru sorgular için hızlı geçici veri saklama sağlayabilir; ancak kalıcılık özellikleri MergeTree ile eşdeğer değildir. Tampon veya dış motorlar önbellek etkisi oluşturabilir; crash kurtarma ve yeniden teslim sırasında geçici verinin kaderi ayrıca incelenmelidir. S3 ya da uzak SQL okumasında fiziksel veri sunucunun yerel belleğinde bulunmasa bile ağ ve çözümleme masrafı oluşur. Performans hesaplaması motorun raporladığı tarama süresinin ötesinde uçtan uca veri aktarımını içermelidir.

### 16.7. Tablo Motorlarının Tutarlılık ve İşletim Özellikleri

Motorlar arasında INSERT atomikliği, birleştirme davranışı, replikasyon ve yeniden başlatma sonrası devam özellikleri değişir. Uygulama SQL arayüzünün benzerliğiyle veri bütünlüğünü eşit kabul etmemelidir. Arıza senaryoları ve sınır durumları test edilmelidir.

Motorların tek bir "en iyi" sıralaması bulunmaz. MergeTree kalıcı büyük analitik tablolarda, Memory küçük geçici ara sonuçlarda, Kafka sürekli olay alımında, Distributed çok düğümlü sorgu yönlendirmede farklı görevler üstlenir. Bir tablo motorunun `INSERT` kabul etmesi ve `SELECT` sonucu döndürmesi, veri tekrarlarının, arka plan dönüşümlerinin ve hata sonrası yeniden başlatmanın aynı şekilde ele alındığını göstermez. Bu koşullar her motor için ayrı sözleşme oluşturur.

## Ünite 17: Veri Atlama İndeksleri, Önbellek ve Bellek Yönetimi

Veri atlama indeksleri granülleri eler; PREWHERE ise filtre için gereken dar sütunları önce okuyup geniş yük sütunlarını yalnız kalan satırlar için getirir.

![Veri atlama ve PREWHERE animasyonu](https://alikoker.com.tr/svg/data-skipping-prewhere.svg "Veri atlama ve PREWHERE")


Veri atlama mekanizmaları her satırı indekste tutmadan ilgisiz granül veya veri parçalarını elemek için kullanılır. Primary index, skipping index, query-condition önbellek ve materyalleştirme stratejileri birbirinden farklı işlevler görür. Yanlış tasarlanmış skip index ek yazma ve depolama maliyeti yaratabilir fakat seçicilik düşükse okunan veriyi azaltmayabilir.

Skip index tasarımında yalancı pozitif sonuç, indeksin aday gösterdiği fakat sorgu koşulunu sağlamayan granule'ların gereksiz okunmasına yol açar. Bu, Bloom filtre için beklenen ödünleşimdir; doğru yapılandırıldığında sorgu sonucunun sessizce eksilmesi beklenmez. Granule'da çok sayıda farklı değer varsa set index verimsizleşebilir; aralık dağılımı genişse minmax filtresi az veri atlayabilir. Öncelik doğal sıralama anahtarı olmalıdır, çünkü sonradan eklenen skip index her INSERT ve birleştirme sırasında bakım gerektirir. Sorgu önbelleği yararlı olsa da yüksek değişiklik ve çok farklı sorgu parametresi altında önbellek hit oranı düşük olabilir. Etkili optimizasyon raporu okunan granül, byte, CPU ve önbellek ısıtılma durumunu birlikte gösterir.

### 17.1. Birincil İndeks Budaması, Veri Atlama İndeksleri ve Yanlış Pozitiflik

Birincil indeks sıralama anahtarının prefix'i üzerinden budama yapar. Bloom tabanlı skipping index yanlış pozitif üretebilir; yanlış negatif üretmemesi beklenen düzgün konfigürasyon, sonuç doğruluğu için temel koşuldur. false-positive arttıkça faydasız granül okuma artar.

Primary index sıralama anahtarına göre seçilen granül aralıklarını daraltabilir. Skip index belirli kolonlarda granül veya indeks bloğunun sorgu değerini içerme olasılığını test ederek ikinci seviye budama sağlar. Bloom filter yanlış pozitif üretebildiği için eşleşmeyen bloğun okunması mümkündür; yanlış pozitif oranı parametrelere bağlıdır. İndeksin varlığını değil `EXPLAIN indexes=1` gibi plan çıktılarını ve okunan byte değişimini değerlendirmek gerekir.

### 17.2. Minmax, Set, Bloom ve Metin İndeksleri

`minmax`, bir granül grubundaki alt ve üst sınırı saklar; aralık ile kesişmeyen blokların okunmasını önleyebilir. `set(N)`, küçük ayırt edici değer kümeleri için uygundur; sınırlı küme kapasitesi dolduğunda atlama yararı azalır. Bloom filter üyelik sınaması olasılıksaldır: yanlış pozitif üretilebilir, doğru kurulan filtrede yanlış negatif beklenmez. Text index, tokenlaştırma ve ters indeks erişimi kullanır; arama operatörünün ilgili indeksle desteklenmesi gerekir.

Mevcut tabloya skipping index eklemek ile geçmiş part'larda indeksi oluşturmak ayrı işlemlerdir:

```sql
ALTER TABLE events
ADD INDEX event_type_skip event_type TYPE set(100) GRANULARITY 4;

ALTER TABLE events
MATERIALIZE INDEX event_type_skip;

EXPLAIN indexes = 1
SELECT count()
FROM events
WHERE event_type = 'ERROR';
```

`MATERIALIZE INDEX`, mevcut veri üzerinde yeniden hesaplama gerektirebilir; büyük üretim tablolarında kaynak tüketimi ve tamamlanma süresi izlenmelidir. Son sorguda indeks tanımının varlığı değil, elenen granül sayısı ve gerçek `read_bytes` değişimi değerlendirilir. Düşük kardinaliteli fakat her granule'da neredeyse bütün değerlerin bulunduğu `event_type` dağılımında indeksin yararı çok az olabilir.

Bloom filtre için n kayıt, m bit ve k hash varsayımıyla yaklaşık yanlış pozitif olasılığı `p ≈ (1 − e^(−kn/m))ᵏ`, uygun hash sayısı `k ≈ (m/n) ln 2` olur. Bu sonuç bağımsız ve dengeli hash varsayımına dayanır; ClickHouse'un gerçek indis boyutu, granularity ve veri dağılımı ayrıca ölçülür. Çok küçük p değeri seçilmesi indeks yazma ve saklama maliyetini artırabilir. Büyük ve rastgele dağılmış string alanlarda Bloom; fiziksel sıralamayla kuvvetle ilişkili sayısal/tarih alanlarında minmax; kelime sorgularında text index ayrı ayrı denenebilir. `LIKE '%...%'` ifadesinin indeks üzerinden hızlanması tokenizer ve fonksiyon desteğine bağlıdır. ClickHouse 26.2'de full-text arama özelliğinin genel kullanıma alındığı duyurulmuştur. [28]

Vektör benzerlik indeksi, sütun bazlı minmax veya Bloom veri atlama indekslerinden ayrı ele alınmalıdır. Seyrek birincil indeks, sıralanmış granül aralıklarını atlar; Bloom filter belirli üyelik sorguları için olası olmayan blokları dışlar; HNSW ise yüksek boyutlu uzayda yaklaşık komşu adaylarını seçer. Bir sorguda zaman filtresi ve vektör benzerliği birlikte kullanıldığında filtrelemenin indeks öncesi/sonrası uygulanması aday sayısını ve recall değerini etkiler. Farklı amaçlara sahip bu indekslerin aynı “hızlanma katsayısı” altında karşılaştırılması yanlış maliyet modeli üretir. [48]

### 17.3. PREWHERE ve Geciktirilmiş Sütun Okuma

PREWHERE önce küçük filtre sütunlarını okuyup eşleşmeyen satırlar için büyük kolon okumayı erteleyebilir. Late materyalleştirme, sonuç için gerek duyulmayan değerlerin üretimini daha ileri aşamaya taşır. Her iki yaklaşımın yararı filtre seçiciliği ve kolon genişliğiyle ölçülür.

`PREWHERE event_type = 'ERROR'` gibi seçici ve dar sütun filtresi, uzun `message` sütununun büyük oranda hiç okunmamasına yardım edebilir. Her koşul otomatik olarak PREWHERE'e taşınmayabilir; optimizer kararını etkileyen tip, ifade ve ayarlar bulunur. Kasten PREWHERE kullandığınızda `EXPLAIN` ve ölçülen `read_bytes` değişimini kontrol edin.
```sql
SELECT
    event_time,
    service_id,
    message
FROM events
PREWHERE event_type = 'ERROR'
WHERE event_time >= now() - INTERVAL 1 HOUR
ORDER BY event_time DESC
LIMIT 100;
```

`PREWHERE`, önce filtre için gerekli sütunları okuyarak eşleşmeyen aralıklarda daha geniş sonuç sütunlarının okunmasını azaltabilir. `WHERE` ile aynı mantıksal filtreyi üretmesi, her durumda aynı fiziksel I/O'yu yaptığı anlamına gelmez. Bir koşul çok az satır eliyorsa filtre sütununu ayrı aşamada okumanın ek maliyeti faydayı aşabilir. Bu nedenle sorgunun `PREWHERE` davranışı, açıklama planı ve veri okuma sayaçlarıyla karşılaştırılmalıdır.

### 17.4. İndeks Seçiciliği ve Maliyet–Fayda Analizi

Bir indeksin yararı, kaç işareti atladığı ve bunun kaç bayt G/Ç önlediğiyle ölçülür. Yüksek false positive veya düşük seçicilikte indeks inceleme CPU'su kazançtan fazla olabilir. Aynı filtrelerin farklı veri dağılımında yeniden ölçülmesi gerekir.

İkincil skipping index eklemek sorgudaki taramayı azaltabilir fakat INSERT ve birleştirme sırasında indeks üstverisi üretme maliyeti ekler. Fayda, indeksin atladığı byte ve sorgu sıklığıyla; maliyet, ek yazma/yer işgali ve bakım süresiyle ölçülür. Düşük seçicilikte her blokta aranan değer bulunduğunda Bloom veya set indeksi neredeyse hiç granül elemez. Deney raporu hem seçilen işaret yüzdesini hem planın yeni indeksi gerçekten kullandığını göstermelidir.

### 17.5. Sorgu, Koşul ve Kullanıcı Alanı Sayfa Önbellekleri

Sorgu önbelleği sorgu sonuçlarının uygun durumlarda yeniden kullanılmasını sağlayabilir; sorgu condition önbellek filtre çıkarımlarının tekrarını azaltabilir. Userspace sayfa önbelleği veri sayfalarını bellekte tutar. Her birinin anahtarlama, geçersizleştirme ve boyut sınırı ayrıdır.

Sorgu sonuç önbelleği, aynı sorgunun sonucunu yeniden hesaplamayı azaltabilir; verinin değişimi ve ayarlardaki farklar önbellek anahtarının geçerliliğini etkiler. Condition önbellek, belirli filtre ve veri parçası bileşimlerinde daha önce değerlendirilmiş sonuçların yeniden kullanımını hedefler. Userspace sayfa önbelleği, depolamadan taşınan blokların bellekte saklanmasına odaklanır. Sonuç, koşul ve veri bloğu önbellekleri farklı doğruluk ve geçersizleştirme sorunlarına sahiptir; hit oranlarını tek bir önbellek metriğinde birleştirmek hatalıdır.

Sonuç önbelleği yalnız sorgu metninin aynı olmasıyla güvenle yeniden kullanılamaz; erişim yetkileri, veri değişimi, ayarlar ve deterministik olmayan fonksiyonlar değerlendirmeye katılmalıdır. `now()` içeren zaman penceresi sorgularında önbelleğe alınmış sonuç, yeni olaylar gelmese bile pencerenin anlamı değiştiği için eskiyebilir. `mark cache` indeks konumlarını, uncompressed önbellek çözümlenmiş veri bloklarını, sorgu önbelleği ise uygun sorgu sonuçlarını saklar; birbirlerinin alternatifi değildir.

Önbellek etkinliğini değerlendirirken tek sorgunun ilk çalışmasıyla tekrarını karşılaştırmak yetersizdir. Aynı anda farklı müşterilerin ve zaman aralıklarının sorguları çalıştığında çalışma kümesinin önbelleğe sığıp sığmadığı ölçülmelidir. Kaynak baskısında önbelleğin boyutunu artırmak işletim sistemi sayfa önbelleği veya toplulaştırma belleği için ayrılan alanı azaltabilir.

26.10'un deneysel `columns cache` mekanizması, belirli MergeTree Wide veri parçası ve Parquet yollarında önceden ayrıştırılmış sütunları bellekte tutar. Bu katman dosya sistemi önbelleğinden farklıdır: ilki çözümlenmiş sütunları, ikincisi okunan dosya baytlarını saklayabilir. Sunumdaki sıcak veri örneğinde 0,26 saniye yerine 0,064 saniye ölçülmüştür. Önbellek isabet oranı yüksek olsa bile kalıcı bellek kullanımının diğer sorgulara etkisi hesaba katılmalıdır. Diskte tutulabilen sonuç önbelleği ise işlenen sütunları değil tamamlanmış sorgunun sonucunu saklar; sorgu metni, veri değişimi ve sonuç geçerliliği farklı önbellek türlerinde ayrı değerlendirilir. Deneysel modun `use_columns_cache` ayarı ve gerçek sürüm uyumluluğu kontrol edilmelidir. [41]

### 17.6. Önbellek Geçersizleştirme ve Sıcak–Soğuk Sorgu Davranışı

Isıtılmış önbellek ile yürütülen sorgu, ilk soğuk okumadan farklı disk ve ağ maliyetine sahiptir. Başarım karşılaştırması sıcak ve soğuk koşulları açıkça ayırmalıdır. Önbellek invalidation veri değişiminin görünürlüğüyle ilgili olduğu için doğruluk testini de kapsar.

Bir sorgu ilk çalışmada diskten veri getirip ikinci çalışmada önbellekten okuyorsa karşılaştırma sıcak/soğuk durumları karıştırmamalıdır. Yeni INSERT, mutation, veri parçası birleştirme ve ayar değişiklikleri farklı önbellek katmanlarını farklı biçimde etkileyebilir. Result cache'deki bir kayıt ile verinin OS page cache'de bulunması aynı geçersizleştirme kuralını izlemez. Kararlı deney, önbellek durumunu ya kontrollü sıfırlar ya da testin sıcak önbellek olduğunu açıkça belirtir.

### 17.7. Bellek Sınırları, Harici GROUP BY/SORT ve Diske Taşma

Büyük GROUP BY veya ORDER BY işlemi bellek sınırına ulaştığında dış depolamaya diske taşma desteklenebilir. Diske taşma çökme önlerken işlem hacmini ve geçici alan ihtiyacını değiştirebilir. Limitler tek sorgu ve sunucu genelinde farklıdır.

Büyük `ORDER BY`, yüksek kardinaliteli `GROUP BY` veya JOIN işlemleri bellek sınırına yaklaşabilir. Disk üzerinde harici sıralama ya da agregasyon etkin olduğunda işlemin tamamlanabilmesi mümkün olsa da gecikme ve geçici disk tüketimi yükselir. Diske taşma kararı verilen aşamada geçici veri miktarı ve disk bant genişliği ölçülmelidir. Bellek limitini sürekli büyütmek, eşzamanlı sorguların toplamda host belleğini tüketmesi riskini artırır.

Belleğe sığmayan agregasyonlarda hash tablosunun bölümleme ve diske taşıma maliyeti, yalnız geçici depolanan baytla ifade edilemez; geçici blokların yeniden okunması, birleştirme ve dosya sayısı ek işlem üretir. 26.9 sürümünde `DISTINCT` için de disk taşması yeteneği duyurulmuştur. Bellek tüketiminin azalması gecikmenin aynı kalacağını garanti etmez. Sınır değerler, `max_bytes_before_external_group_by` gibi ayarların kullanılan operatör ve sürüm bakımından geçerliliği kontrol edilerek belirlenmelidir; bir operatörün diske taşma ayarının başka operatöre uygulanacağı varsayılmaz.

Diske taşma testinde veri kümesinin benzersiz grup sayısı bilinmeli, sorgu sonucu bellek limitinden bağımsız olarak doğrulanmalı ve temp disk dolduğunda oluşan hata senaryosu da ölçülmelidir. Bellek sınırını aşan sorguyu başlatamamak ile yürütme sırasında geçici disk yetmezliği iki ayrı hata sınıfıdır.

26.10'da `IN (subquery)` sonucu oluşturulan büyük kümenin diske taşınmasına izin veren `max_bytes_before_external_set` ayarı eklenmiştir. Varsayılan değer sıfır olduğundan mekanizma açık kabul edilmemelidir. Bellekte tutulan bir kümenin sorted run'lara aktarılması, ek G/Ç ve erişim maliyetine karşılık bellek üst sınırı sağlamaya yardımcı olur. Resmi örnekte bellek-içi çalışma 12,9 GB gerektirirken 4 GB sorgu sınırında hata oluşturmuş; disk taşması kullanıldığında yaklaşık 1,0 GB bellekle 30 saniyede tamamlanmıştır. Bellek kazanımı, sürenin kısalacağı anlamına gelmez. Temp dizininin kapasitesi, disk doygunluğu, iptal sonrasında dosya temizliği ve aynı anda taşan sorgu sayısı ayrıca denetlenmelidir. [41]

### 17.8. Bellek Aşımı ve Yetersiz Bellek Senaryoları

Memory overcommit ve OOM mekanizmaları bellek doygunluğunda hangi sorgunun sonlandırılabileceğini etkiler. Linux OOM killer süreç düzeyinde yıkıcı sonuç doğurabilir. Limitlerin yalnız artırılması bellek sızıntısı veya sınırsız kardinaliteli GROUP BY sorununu çözmez.

Sorgu memory limit ile fiziksel RSS aynı metrik değildir; bellek ayırıcı havuzları, önbellekler ve izleme dışı kalabilecek kalemler arasında fark oluşabilir. Overcommit mekanizması bellek baskısı sırasında bir sorgunun durdurulmasına izin verebilir, ancak bütün istemcilere eşit hizmet garantisi vermez. OOM tanılamasında aynı anda çalışan sorgular, birleştirme/insert yükü ve host/cgroup sınırları birlikte incelenir. Sorgu iptalinin gerçekleşmesiyle istemcinin veri aktarımını ne kadarının aldığı da ayrı değerlendirilmelidir.

## Ünite 18: İleri SQL, İstatistik ve Zaman Serisi Analizi

Analitik SQL'in güçlü tarafı yalnız GROUP BY değildir; istatistiksel tahmin, yüzdebirlik hesapları, zaman pencereleri, toplu diziler ve birleştirilebilir agregasyon durumları da temel işlevlerdir. Kesin sonuç gerektiren sorgularla yaklaşık algoritmalar farklı doğruluk garantileri sunar. Örneğin `uniq()` bellek ve hız için tahmin üretirken `uniqExact()` yüksek kardinalitede daha fazla durum saklayabilir.

İstatistiksel fonksiyon kullanırken sonuç türünü ve örneklem varsayımını açıklamak gerekir. Popülasyon varyansıyla örnek varyansı farklı paydalara sahiptir; bu ayrım n küçükken belirginleşir. Çok büyük olay veri kümelerinde quantile tahmini için kullanılan özet algoritmaların bellek kullanımı genellikle tam sıralama istatistiğinden farklıdır; ancak yakın yüzdebirliklerde kabul edilebilir hata p99 SLA kontrolünde hayati olabilir. `avgState` ve `avgMerge`, toplam ve adedi birleştiren bir durum semantiğine sahiptir; iki saatlik ortalamayı aritmetik ortalamayla birleştirmek saatlik satır sayıları farklıysa yanlış sonuç doğurur. Kullanıcı sayısı, oran ve ortalama gibi ölçülerde yanlış rollup yapmamak için başlangıç olgu tanecikliği ve state sözleşmesi korunmalıdır.

### 18.1. Aritmetik, Mantıksal ve Dönüştürme Fonksiyonları

Türe dönüştürme sırasında taşma, negatif/pozitif işaret, sabit ölçek ve NULL davranışı hesapları değiştirebilir. Bölme, mod ve koşullu ifadelerde kaynak tipleri korunmalıdır. Sorgu optimization sonucunu doğru yorumlamak için sonuç türü ve precision belirlenir.

Aritmetik ifadelerde tamsayı bölmesi, kayan nokta dönüşümü, `NULL` propagasyonu ve taşma sonucu sayısal tipten etkilenir. Ölçü birimi de tip kadar önemlidir: nanosaneyi milisaniye gibi yorumlayan bir sorgu, teknik olarak hata vermeden yanlış istatistik üretir. Zaman aralıkları için koşulun başlangıçta dahil, sonda hariç kurulması (`[başlangıç, bitiş)`) komşu periyotlarda çift sayımı önleyebilir.

Sayısal ifade değerlendirmesinde `Decimal` ölçeği, dönüştürme sırası ve overflow davranışı raporun sonucunu değiştirebilir. Parasal tutarın önce Float64'e çevrilip sonra `sum()` ile birleştirilmesi, kaynak sistemdeki sabit noktalı hesapla aynı yuvarlama sonucunu garanti etmez. Dönüşüm stratejisi; giriş türü, ara işlem türü ve hedef kolon türü için ayrı belirtilmelidir. Hata toleransına dayanan yaklaşık hesaplarda mutlak hata |x̃ − x| ve bağıl hata |x̃ − x|/|x| kavramları ayrılır; sıfıra yakın gerçek değerlerde bağıl hata kararsız olabilir.

### 18.2. Dize, Düzenli İfade, Dizi ve İç İçe Veri İşlemleri

UTF-8 metin boyutu byte sayısına eşit karakter sayısı değildir. Regex ve metin işleme büyük hacimde yüksek CPU tüketebilir; sık kullanılan alanlar besleme sırasında tipli sütunlara ayrılabilir. `arrayJoin` dizileri satırlara açarak sonuç kardinalitesini büyütür.

`Array` içindeki elemanlar satır başına değişken sayıda olabilir; `ARRAY JOIN` bunları farklı satırlara açarak cardinality artışı yaratır. Regex ve metin dönüştürme işlemleri düşük maliyetli sayısal karşılaştırmadan daha pahalı olabilir. JSON alanlarında sorgu anında her kaydı ayrıştırmak yerine sık sorgulanan alanların typed sütun olarak tutulması düşünülebilir. Buna karşılık seyrek veya hızla değişen özniteliklerin tümünü sabit kolonlara ayırmak şema bakım maliyetini artırır.

### 18.3. Sum, Avg, Count, Min/Max, argMin/argMax

`sumIf`, `countIf`, `argMin`, `argMax` gibi fonksiyonlar koşullu toplama ve belirli ölçüye göre ilişkili değeri seçmeyi sağlar. `argMax(value, time)` eşit zamanlarda tek başına deterministik bir tie-break garanti etmez. Gerekiyorsa zaman+sürüm sırası tasarlanır.

`sum` ve `count` çoğu raporda birleşebilir ölçülerdir; `avg` doğru genel ortalama için toplam ve gözlem sayısını birlikte gerektirir. `argMin(x, t)` veya `argMax(x, t)`, t değerinin minimum/maksimum olduğu satırdaki x değerini seçebilir. Birden çok satırda aynı uç değer bulunursa eşitlik bozma ölçütü açıkça belirtilmeden deterministik tek sonuç beklenmemelidir. Sonuç doğruluğu için gereken durum ile tek sayı halinde saklanan sonuç birbirinden ayrılmalıdır.

### 18.4. Variance, Stddev, Covariance, Correlation, Skewness, Kurtosis

Örnek varyansı paydada n−1, popülasyon varyansı n kullanır; fonksiyon seçimi istatistiksel yorumu etkiler. Kovaryans ve korelasyon farklı boyutları temsil eder; ilişki nedenselliği kanıtlamaz. Sayısal kararlılık büyük-küçük değer farklarında test edilir.

Örnek varyans hesabında `varSamp` benzeri fonksiyonlar paydada n−1, popülasyon varyansında ise n kullanır; küçük örneklemlerde fark önemli olabilir. Korelasyon katsayısı sıfıra yakınsa doğrusal ilişki zayıftır; bunun nedensizlik veya bağımsızlık anlamına gelmediği unutulmamalıdır. Çarpıklık ve basıklık özellikle ağır kuyruklu ağ gecikmelerinde dağılımın yalnız ortalama ve varyansla açıklanamadığını gösterebilir. Sayısal kararlılık için büyük değerlerin naif kare toplamlarından varyans türetmek risklidir.

### 18.5. QuantileExact/TDigest, Uniq/uniqExact, topK

Tam quantile ve yaklaşık TDigest sonuçları, yüksek kardinaliteli `uniqExact` ve yaklaşık uniq fonksiyonları bellek ile doğruluk arasında farklı dengeler sunar. Çok yüksek yüzdeliklerde az sayıdaki kuyruk örneği önem kazandığından tahmin hatası kullanım senaryosuna göre ölçülür.

P95 sorgusu her servis için olay sürelerinin 95. yüzdeliğini hesaplar. `quantileExact` tam sıralama istatistiği oluştururken yaklaşık quantile fonksiyonları yüksek kardinalite ve büyük N için daha uygun olabilir. Aynı veriyle `quantileExact(0.95)` ve seçilen yaklaşık fonksiyon karşılaştırılıp mutlak hata `|q_tahmin − q_kesin|`, bağıl hata `|q_tahmin − q_kesin| / max(|q_kesin|, ε)` hesaplanır. Sıfıra yakın q değerlerinde bağıl hata yanıltıcı olabilir.
```sql
SELECT
    service_id,
    count() AS n,
    avg(duration_ms) AS mean_ms,
    quantileExact(0.95)(duration_ms) AS p95_ms,
    max(duration_ms) AS max_ms
FROM events
WHERE event_time >= now() - INTERVAL 1 DAY
GROUP BY service_id
ORDER BY p95_ms DESC;
```

Yaklaşık benzersiz sayımda bellek tüketimi, hata modeli ve tahminin birleştirilebilirliği birlikte önemlidir. `uniqExact` benzersiz anahtar kümesinin büyüklüğü arttıkça belleği artırabilir. Yaklaşık tahminleyiciler sınırlı bir durumla yüksek kardinaliteyi hesaplayabilir, ancak sonucu kesin sayı gibi kullanmak hatalıdır. Farklı saatlerdeki benzersiz kullanıcı sayılarını toplamak, aynı kullanıcının başka saatlerde görülmesi nedeniyle çift sayım doğurur; ara durumlar birleştirilmelidir.

Yüzdelik hesaplamada `quantile` ile `quantileExact` ayrımı gözlem sayısı, hata toleransı ve bellek bütçesi açısından ele alınır. Örneğin her servis için p99 gecikmesini hesaplayıp servislerin p99 değerlerinin ortalamasını almak, bütün olayların p99'unu vermez. Yüzdelik fonksiyonların bazı varyantları deterministiklik ve paralel yürütme etkileri bakımından da farklı olabilir. İstatistiksel raporda sayım yöntemi, kullanılacak agregasyon fonksiyonu ve hata hedefi açıkça tanımlanır.

Yaklaşık distinct sayımı ve quantile fonksiyonları aynı istatistiksel hata modeline sahip değildir. `uniqExact` kümedeki ayırt edici değerleri kesin sayar; uygun yaklaşık yöntemler cardinality büyüdükçe bellek tüketimini sınırlamak üzere özet durum tutar. T-Digest tabanlı quantile, örnekleri centroid durumlarına sıkıştırır; uç quantile davranışı veri dağılımı, state birleştirme düzeni ve parametrizasyona göre değişebilir. Yaklaşık sonucun toleransı tek bir evrensel yüzdeyle ifade edilemez.

p99 gecikmesi için 10.000 gözlemde üst yüzde birlik bölüm yalnız 100 örnekten oluşur. Ağır kuyruklu veride birleştirilmiş alt dönem p99'larının aritmetik ortalaması, genel p99'u vermez. Kesin p99 gerekiyorsa ham örnek veya exact quantile kullanılmalı; yaklaşık yöntem seçilmişse eşdeğer veri kümesinde exact referansa göre mutlak ve göreli hata hesaplanmalıdır. `topK`, sıklığı yüksek değerler için aday üretir; düşük frekanslı bütün değerleri eksiksiz veren bir `GROUP BY` yerine geçmez.

### 18.6. If, State, Merge ve MergeState Birleştiricileri

`sumState(x)` bir ara durumu, `sumMerge(state)` bu durumları birleştirmeyi sağlar. `If` combinator koşul, `State` durum üretimi, `Merge` durum birleştirme semantiğidir. Yalnız sayısal sonuçları ortalayıp tekrar toplamak, doğru aggregate state işlemi değildir.

Agregasyon combinator'ları aynı temel fonksiyona farklı koşul, giriş veya durum semantiği ekler: `sumIf(x, koşul)` koşullu toplam, `sumState(x)` ara durum, `sumMerge(state)` ise bu durumların birleştirilmesi için kullanılır. Bu mekanizma ön hesaplanmış özetleri yeniden toplamayı mümkün kılar. Ancak her fonksiyonun her combinator ile tanımlanmış olduğunu varsaymak veya state sütununu doğrudan nihai sayı gibi okumak hatalıdır.

`avgState(x)` ile üretilen ara sonuç, iki grubun ortalaması değil birleşebilir toplam–sayı bilgisidir. Alt sorgu düzeyinde `avgMerge(state)` uygulandığında veri gruplarının büyüklükleri doğru ağırlıklandırılır. Birleşim sırası desteklenen agregasyon fonksiyonunun durum cebrine bağlıdır. Düşük kardinaliteli gruplarda exact distinct kullanılabilirken çok sayıda grup ve milyarlarca olayda yaklaşık durumların bellek maliyeti belirleyici olabilir.

Koşullu agregasyonda `sumIf(bytes, is_error)` ve `countIf(is_error)` farklı ölçülerdir: ilki hatalı olayların bayt toplamını, ikincisi hata sayısını üretir. Koşulun NULL değerlerde nasıl değerlendirildiği veri kalitesi sözleşmesiyle uyumlu olmalıdır. `If`, `State`, `Merge` ve `OrNull` benzeri combinator'ların uygun birleşimleri sistem sürümündeki fonksiyon kataloğuyla doğrulanır.

### 18.7. Pencere Fonksiyonları, Elde Tutma, Huni ve Zaman Gruplama Analizi

Window functions satırları yok etmeden bölüm ve order içinde hesaplama yapar. Retention ve funnel analizinde olay sırası ile kimlik sözleşmesi gereklidir. `toStartOfInterval` sabit zaman kovaları üretir; UTC ve yerel takvim saati ayrımı kaçınılmazdır.

Zamansal kovalarla özetleme:

```sql
SELECT
    service_id,
    toStartOfInterval(event_time, INTERVAL 15 MINUTE) AS bucket,
    count() AS events,
    sum(bytes_sent) AS bytes
FROM events
WHERE event_time >= now() - INTERVAL 1 DAY
GROUP BY service_id, bucket
ORDER BY service_id, bucket;
```

Eksik kovalar sorgu sonucunda otomatik üretilmez; sıfır olay ile eksik gözlem ayrı modellerdir.

Pencere hesapları ile zaman kovalarının veri doğruluğu ayrı ele alınmalıdır. Retention oranı Rₜ = |U₀ ∩ Uₜ| / |U₀| biçiminde tanımlandığında U₀ başlangıç kohortu, Uₜ ise hedef pencerede gözlenen tekil kullanıcılar kümesidir. Her iki kümenin kimlik normalizasyonu ve zaman sınırı aynı olmalıdır. DISTINCT kullanıcı sayılarının birbirinden çıkarılması veya toplam olay sayısına bölünmesi retention üretmez. Zaman dilimi değişiminin yaşandığı günlerde 24 saatlik sabit pencere ile takvim günü farklı uzunluklara sahiptir. `toStartOfInterval` ile oluşturulan kova sınırı, veri alımından önce belirlenmiş kaynak zaman dilimi sözleşmesiyle uyuşmalıdır.

### 18.8. Yaklaşık Algoritmaların Hata ve Bellek Maliyetleri

Approximate cardinality/quantile algoritmalarında hata dağılımı veri dağılımı ve parametrelere bağlıdır. Bir sorgunun daha hızlı olması belirli yüzdelik için kabul edilebilir hataya sahip olduğunu göstermez. Başarım karşılaştırması sonuçları hem süre hem mutlak/bağıl hata ile raporlanır.

Yaklaşık kardinalite ve quantile algoritmaları bellek/verimlilik kazanımını ölçüm hatasıyla değiştirir. Quantile sonucundaki hata, toplam satır sayısına ve değer dağılımına bağlı olarak kesin varyans gibi davranmayabilir. Bir P99 sorgusunda az görülen uç değerlerin korunması kritikse exact ve approximate sonuçlar aynı veri örnekleminde karşılaştırılmalıdır. Yöntem seçilirken hesaplama süresi yanında deterministik tekrar üretilebilirlik, birleştirme sırası duyarlılığı ve bellek kullanımı raporlanmalıdır.

Kardinalite tahmininde bazı HyperLogLog türevleri için bağıl standart hata yaklaşık 1,04/√m biçiminde modellenebilir; `m` kayıt hücresi sayısıdır. Örneğin 16.384 hücre için yaklaşık %0,81 elde edilir. Bu değer tüm `uniq` varyantları için sabit garanti değildir; ClickHouse fonksiyonunun kullandığı algoritma, veri dağılımı ve sürüm bilgisi esas alınmalıdır. Yaklaşık bir sonucun mutlak hata toleransı da ölçekle büyür: 20 milyon farklı kullanıcı için %1 hata yüz binlerce kayıt düzeyindedir.

Yüzdelik değer tahmininde de örnek hacmi ve kuyruk dağılımı önemlidir. `quantileTDigest(0.99)` belleği sınırlamak için özet yapısı kullanır; doğruluk gerektiren denetimlerde `quantileExact` ile karşılaştırılması gerekir. Özellikle birbirinden bağımsız gruplarda dağılımın farklılaşması, tek bir küresel hata oranını bütün gruplara taşımayı geçersiz kılar. Ölçülen hata `|q_tahmin − q_referans|` ve gerekirse normalize edilmiş karşılığı üzerinden raporlanır.

Yaklaşık en yakın komşu aramasında doğruluk genellikle *recall@k* ile değerlendirilir: sorgunun döndürdüğü ilk k aday içindeki gerçek ilk k komşularının sayısı k'ya bölünür. Bu ölçüt klasik `uniq` ya da quantile yaklaşıklığının hata metriğiyle aynı değildir. HNSW için bağlantı grafiği, `ef` türü arama genişliği ayarları ve nicemleme hassasiyeti; arama gecikmesi ile recall arasında değiş tokuş oluşturur. Filtreli vektör aramasında önce daraltma ve sonra ANN araması ile önce ANN ve sonra filtreleme yöntemlerinin sonuç kalitesi farklı olabilir. Kesin `ORDER BY cosineDistance(vector, q) LIMIT k` sorgusu, aynı mesafe işleviyle yaklaşık indeks sonucunu karşılaştırmak için referans olabilir; N × d büyüklüğündeki tam taramanın maliyeti ayrıca raporlanmalıdır. [48]

### 18.9. PRQL, KQL, LogsQL ve Alternatif Sorgu Dilleri

PRQL, KQL veya LogsQL gibi sorgu arayüzleri belirli kullanım deneyimleri sunabilir; destek düzeyi, parser ve sürüm bağımlılığı farklıdır. Kritik SQL üretiminde bu dillerin standard SQL'e dönüşümü ve sonuç semantiği kontrol edilir.

Alternatif sorgu dillerinin amacı çoğunlukla analitik ifadeyi farklı kullanıcı profilleri için daha kolay kurulabilir hale getirmektir. Ancak bir dilin ClickHouse üzerinde çalışan dönüştürücüsünün bulunması, ClickHouse sunucusunun o dili yerel olarak ayrıştırma ettiği anlamına gelmez. PRQL gibi SQL'e derlenen dillerde üretilen SQL'i görmek ve sorgu planını ölçmek mümkündür. LogsQL veya KQL benzeri sorgular taşınırken regex, tokenizasyon, zaman aralığı ve null eşitliği yeniden doğrulanmalıdır.

26.10 sürümünde LogsQL, Trino ve Kusto sözdizimlerine ilişkin yeni uyumluluk seçenekleri sunulmuştur. LogsQL deneysel bir sorgu lehçesi olarak ayrıştırma aşamasında ClickHouse `SELECT` ifadelerine dönüştürülür; Elasticsearch DSL, SQL ve LogsQL aynı sorgu dili değildir. Trino ve Kusto lehçelerinin Beta düzeyi, her fonksiyonun ve hata davranışının eksiksiz eşdeğer olduğunu göstermez. Uygulamada SQL üreten istemciler için sürüm, etkin dialect, zaman türleri ve null davranışı sabitlenmeden sorgu taşınabilirliği kabul edilmemelidir. [41]

26.8 ile tanıtılan pipelined SQL, bir kaynaktan başlayan dönüşümlerin `|>` operatörü üzerinden art arda ifade edilmesini sağlar. Bu sözdizimi SQL'deki ilişkisel işlemlerin yerini değiştirmez; filtre, toplama ve sıralama aşamalarının daha doğrusal yazılmasını amaçlar. Aynı `events` tablosundaki durum kodu dağılımı şu biçimde sorgulanabilir:

```sql
FROM events
|> WHERE service_id = 42
|> AGGREGATE count() AS event_count GROUP BY status_code
|> ORDER BY event_count DESC;
```

Bu ifade ile klasik `SELECT status_code, count() ... GROUP BY status_code` biçimi, aynı veri kesiti ve ayarlarla aynı grupları üretmelidir. `|>` ifadesinin yürütme için zorunlu yeni bir veri yapısı oluşturduğu ya da tek başına daha hızlı sorgu verdiği çıkarılamaz. Uyumluluk testi sunucu sürümünü ve etkin SQL lehçesini kapsar. [46]

## Ünite 19: JOIN Algoritmaları ve Harici Sözlükler

JOIN maliyeti yalnız satır sayısına bağlı değildir. Hash tablosu belleği, sıralama maliyeti ve veri dağılımı hangi algoritmanın uygun olduğunu belirler.

![JOIN algoritmaları ve bellek animasyonu](https://alikoker.com.tr/svg/join-algorithm-memory.svg "JOIN algoritmaları ve bellek maliyeti")


Analitik JOIN maliyeti yalnız tablo boyutuna değil, eşleşme çokluğuna, sağ tablonun bellekte tutulan temsilinin büyüklüğüne ve anahtar dağılımına bağlıdır. ClickHouse, farklı JOIN algoritmaları ve harici sözlük erişimleri sunar. Şema tasarımında sık kullanılan küçük boyutların önceden zenginleştirilmesi yararlı olabilir; ancak veri geçmişinin tutarlılığı ve boyutun güncellenme sıklığı hesaba katılır.

JOIN algoritmasını değerlendirmede sağ tablonun belleğe sığması, anahtar dağılımı ve fanout önemlidir. Örneğin tek bir `service_id` değeri sağ tabloda yüz bin eşleşme taşıyorsa `ALL JOIN` sol tarafta az satır olsa bile çok büyük çıktı doğurabilir. Bu nedenle sorgu cardinality tahmini yalnız kaynak tablo satır sayısına indirgenemez. Dictionary lookup daha küçük ve belirli anahtarla sorgulanan boyutlarda alternatif olabilir; önbellek ömrü geçmişi etkiler. ASOF JOIN zamansal en yakın kaydı seçerken kaynak olayların zaman sıralamasını ve güncelleme akışını doğru taşımak zorundadır. Boyut değerlerinin aynı anda Oracle ve ClickHouse'da farklı görünmesi, analitik sonuçta geçici uyumsuzluk yaratabilir.

### 19.1. ALL/ANY/SEMI/ANTI/ASOF JOIN Türleri

ALL JOIN bütün eşleşmeleri, ANY uygun eşleşmelerden birini temsil eder; SEMI/ANTI üyelik koşullarını, ASOF sıralı zamansal yakınlığı kullanır. ANY seçiminin birden çok eşleşme için hangi satırı döndürdüğü deterministik varsayılmamalıdır. ASOF senaryosunda sıralama ve saat doğruluğu ayrıca önemlidir.

`ALL JOIN` eşleşen bütün satır kombinasyonlarını üretirken `ANY JOIN` eşleşmelerin sayısını sınırlayabilir. `SEMI JOIN` varlık denetimi, `ANTI JOIN` eşleşmeyen kayıtları seçme, `ASOF JOIN` ise sıralı zaman veya benzer yakınlık koşulları için önemlidir. Çoktan çoğa JOIN sonuç satır sayısını çarpan etkisiyle büyütebilir. Yanlış JOIN türü hem sorgu performansını hem de raporlanan toplamı bozabileceği için kardinalite testleri yapılmalıdır.

ClickHouse 26.10 ile tanıtılan deneysel `LATERAL JOIN`, sol taraftaki satırlara başvuran alt sorguların `FROM` içinde tanımlanmasını sağlar. Uygunlaştırma aşaması, bağımlı alt sorgunun her dış satır için ayrı başlatılması yerine birleştirilmiş plana dönüştürülmesine imkan verir. En yüksek iki olayı servis başına seçme türündeki sorgularda önce grup başına deterministik sıralama tanımlanmalıdır; yalnız `LIMIT 2` kullanmak aynı zaman damgasındaki eşitlikleri kendiliğinden çözmez. Deneysel mod `allow_experimental_lateral_join` ile açılır. Daha eski sürümlerde `LIMIT BY`, pencere fonksiyonu veya özet tablo aynı hedefi farklı maliyetlerle gerçekleştirebilir. Her yöntemin sonuç eşdeğerliği, aynı anda gerçekleşen olaylar ve NULL anahtarlar bakımından karşılaştırılmalıdır. [41]

### 19.2. Hash, Partial/Full Birleştirme, Direct, Grace-hash JOIN

Hash JOIN sağ tarafın hash yapısını bellekte tutabilir; sort-birleştirme sıralı akışlar üzerinde çalışır; grace-hash diske bölümleme imkanı sunar. Direct JOIN bazı sözlük veya anahtar-değer erişimlerinde faydalıdır. Algoritma seçimi sürüm, ayarlar ve veri hacmine göre değişir.

JOIN ölçümünde sağ tablo 30 milyon satır, ortalama anahtar+yük 48 bayt ise yalnız ham satır yükü yaklaşık 1,44 GB'dır. Hash düğümleri, bucket dizileri, allocator overhead ve geçici kolonlar bu tutardan fazlasını isteyebilir. `join_algorithm` seçimiyle diske taşma veya birleştirme tabanlı yöntemlerin değerlendirilmesi tek makinenin RAM sınırını aşan veri kümelerinde önemlidir. Her ikili SQL JOIN aynı algoritmanın sabit maliyetine sahip değildir.

JOIN yürütmesinde sağ tarafın hash tablosuna alınması klasik `hash` yaklaşımının temelidir. `Nᵣ` sağ tarafta satır sayısı ve `wᵣ` satır başına yapı yükü olsun. Yaklaşık bellek gereksinimi `O(Nᵣ × wᵣ)` büyüklüğündedir; gerçek bellek hash yük faktörüne, anahtar kodlamasına, satır referanslarına ve allocator davranışına bağlıdır. Bellek büyükse grace hash JOIN verileri disk bölümlerine ayırabilir; birleştirme JOIN sıralı akışlardan yararlanır. Direct JOIN ise uygun bir anahtar–değer kaynak üzerinden arama yapabilir. Algoritma tercihi sorgu gecikmesini olduğu kadar peak memory ve harici disk erişimini de değiştirir.

Bir milyar olayla on milyonluk boyut tablosunu birleştiren sorguda boyut tarafındaki düşük kardinaliteye uygun denormalizasyon veya dictionary lookup, her sorguda büyük hash tablosu kurmaktan daha ucuz olabilir. Buna karşılık boyut tablosu sık güncelleniyorsa önceden zenginleştirilen olayların düzeltme maliyeti doğar. `ANY JOIN`, çoğaltıcı çoklu eşleşmeleri sınırlar; ancak hangi eşleşmenin doğru olduğu kaynak iş kurallarınca belirlenmemişse yanlış raporlamaya yol açabilir. JOIN optimizasyonu semantik karşılıklılığı bozmadan yapılmalıdır.

Modern ClickHouse sürümlerinde optimizer'ın join reordering ve runtime filtering yetenekleri sürümler arasında önemli ölçüde gelişmiştir. ClickHouse'un Haziran 2026 tarihli kendi TPC-H SF100 çalışmasında JOIN ağırlıklı iş yükünün 22.4–26.4 sürümleri arasında 26 kat hızlandığı raporlanmıştır; bu, PostgreSQL veya Oracle karşısında evrensel 26 kat üstünlük değil, aynı ürünün sürümleri arasındaki ölçülmüş farktır. Kaynak: https://clickhouse.com/blog/clickhouse-fast-joins

Hash JOIN'in build aşamasında sağ tarafın eşleştirme anahtarlarıyla hash tablosu oluşturulabilir; tabloya ayrılan bellek yalnız satır genişliği değildir: bucket dizileri, hash üstveri, ek hizalama ve çakışma maliyeti vardır. Grace-hash JOIN her iki girdiyi anahtarın hash değerine göre partition'lara ayırarak belleğe sığmayan tabloların parça parça eşleştirilmesini sağlar; karşılığında disk okuma-yazma ve partitioning maliyeti oluşur. Sort-birleştirme yaklaşımında iki taraf anahtara göre sıralanmışsa sıralama gideri düşebilir; aksi durumda dosya-temelli external sort pahalıdır.

Direct JOIN yalnız uygun sağ taraf erişimi ve JOIN semantiği altında dictionary benzeri key lookup kullanabildiğinde avantajlıdır. `join_algorithm='auto'` ile bellek sınırına ulaşıldığında algoritma değişebilir; bunun sürüme bağlı davranışı `EXPLAIN` ve trace ile doğrulanmalıdır. Doğru algoritma sorguya, dağılıma, eşleşme oranına ve bellek kısıtına bağlıdır. Kaynak: https://clickhouse.com/blog/clickhouse-fully-supports-joins-how-to-choose-the-right-algorithm-part5

26.10 sürümünde büyük hash tablolarının Robin Hood hashing düzenine geçirilmesi bellek doluluk oranını ve probe davranışını değiştirmiştir. Bir anahtarın başlangıç konumundan uzaklığı arttığında daha kısa arama mesafesine sahip anahtarla yer değiştirilmesi, probe uzunluğu dağılımının uç değerlerini sınırlamaya yardımcı olur. Üreticinin 100 milyon farklı değer üzerinde yayımladığı `uniqExact` örneğinde bellek 13,5 GB'tan 4,6 GB'a, süre 1,33 saniyeden 0,31 saniyeye düşmüştür. Bellek azalması yaklaşık %65,9; hızlanma 1,33/0,31 ≈ 4,29 kattır. Bunlar üreticinin belirli veri kümesi ve yapılandırma sonuçlarıdır; her JOIN veya GROUP BY için sabit katsayı sayılmaz. [41]

Yük faktörü α = n/m ile gösterilsin; n dolu kova sayısı, m kapasitedir. Daha yüksek α bellek yükünü azaltır, fakat çakışma çözümünün beklenen ve uç probe maliyetini etkiler. Robin Hood tekniğinin faydası yalnız α artışına değil anahtar dağılımına, hash fonksiyonuna, allocator giderine ve vektörleştirilmiş probe uygulamasına bağlıdır. Karşılaştırmada kaydedilen metrikler sonuç kardinalitesi, hash bellek zirvesi, CPU zamanı ve çıktı eşitliğidir.

### 19.3. Hash Tablosu Oluşturma, Arama, Kardinalite ve Bellek Maliyeti

Hash tablosunu oluşturma aşaması bellek tahsisini, arama aşaması sol taraftaki satırların eşleştirilmesini belirler. Düşük seçicilik ya da birden çoğa ilişki sonuç satırlarını çarpabilir. JOIN'den önce filtreleme ve gereksiz sütunları çıkarmak ara veri hacmini düşürür.

Hash JOIN'de build tarafı için bellek maliyeti kabaca O(N_build × (anahtar_baytı + yük_baytı + yönetim_payı)) olarak büyür; pratik kapasite hesabı hash tablosu doluluk oranını da içermelidir. Probe tarafının N_probe satırı için erişim maliyeti seçicilik ve anahtar dağılımına bağlıdır. Büyük tarafın build yapılması gereksiz bellek taşmasına yol açabilir. Join algoritması seçiminde yalnız tablo satır sayısı değil filtrelenmiş giriş boyutu, anahtar kardinalitesi, NULL semantiği ve geçici disk alanı değerlendirilir.

26.10'da sıralı birleştirme JOIN akışının birincil anahtar aralıkları üzerinden paralel alt işlemlere ayrılması, sıralama maliyeti zaten ödenmiş veri kümelerinde dar boğazı azaltabilir. Sunumdaki seçilmiş örnekte 9,1 saniyeden 0,78 saniyeye düşüş bildirilmiştir. Bu oran, anahtarların uygun sırada olması ve aralıkların yeterince dengeli bölünmesi koşullarıyla anlamlıdır. Ağ üzerinden dağıtılmış JOIN veya ön sıralama gerektiren iş yüklerinde maliyet modeli değişir. JOIN `ON` koşullarının genişletilmesi de optimizer'ın her koşulda hash eşitliğinden yararlanabildiğini göstermez; eşitlik dışı koşulların bulunduğu planlarda olası kombinasyonların sayısı kontrol edilmelidir. [41]

### 19.4. Harici Sözlükler, Yerleşim, Kaynaklar, Yenileme ve Önbellek

Harici dictionary hash, flat, hashed, önbellek veya hierarchical düzenlerde kurulabilir; kaynak yenileme politikası eski değer okuma penceresi doğurur. Dictionary uygun anahtar kimliğine ihtiyaç duyar. Eksik anahtar ve NULL dönüşü açıkça test edilir.

Harici sözlük bir anahtarın boyut bilgisine hızlı erişim sağlamak için kullanılabilir. Tam bellek içi, önbellek tabanlı ve hiyerarşik layout seçenekleri aynı güncelleme ve bellek davranışına sahip değildir. Sözlüğün refresh süresi dolduğunda eski boyut bilgisinin kullanılabilmesi raporlama doğruluğunu etkiler. Sürekli değişen kaynakta sözlüğün güncel kalma hedefi ile lookup gecikmesi karşılaştırılır; kaynak başarısız olduğunda cache'de kalan değerin kullanılma politikası ayrıca belirlenmelidir.

ClickHouse 26.8'de iki eşitsizlik koşulu içeren belirli JOIN sınıfları için sıralama temelli IEJoin algoritması desteklenmiş, ayrıca paralel sıralama-birleştirme JOIN ve dağıtık plan maliyetleme iyileştirmeleri duyurulmuştur. İki olay aralığının örtüşmesi gibi `a.start_time < b.end_time AND b.start_time < a.end_time` koşulları, eşitlik anahtarından farklı bir aday üretimi gerektirir. Bu durumda bütün satır çiftleri üzerinden CROSS JOIN + filtre işleminin O(N × M) karşılaştırma üst sınırı ile sıralama temelli aday daraltma aynı değildir; yine de veri dağılımı, eşitsizlik seçiciliği, ara sonuç boyutu ve planlayıcı seçimi belirleyicidir. `EXPLAIN` algoritma seçimini, gerçek ölçümler ise yararlı etkisini doğrular. [46]

### 19.5. dictGet ile Anahtar Tabanlı Veri Zenginleştirme

`dictGet` olay satırının tanımlayıcısını açıklayıcı alana dönüştürebilir. Aynı lookup milyonlarca satırda yapılacaksa önbellek davranışı ve sözlük cardinality ölçülür. Güncel boyut değeriyle geçmiş olayların zenginleştirilmesi raporun tarihsel yorumunu değiştirebilir.

`dictGet` belirli anahtara karşılık gelen sözlük alanını sorgu sırasında getirebilir. Bu yaklaşım küçük boyut tablolarında JOIN kurma maliyetini azaltabilir, fakat her satır için çok sayıda sözlük erişimi yapılması yüksek hacimli taramada yeni darboğaz yaratabilir. Sözlük anahtarının boş veya bulunamayan değeri ile gerçek NULL semantiği birbirinden ayrılmalı; boyut alanlarının olay zamanına göre tarihsel karşılığı gerekiyorsa yalnız güncel sözlük kullanılması yeterli olmayabilir.

### 19.6. JOIN Yerine Denormalizasyon ve Materyalleştirme

Denormalizasyon JOIN'i okuma yolundan çıkarır fakat boyut değiştiğinde geçmiş satırları yeniden yazmayı gerektirebilir. Materyalleştirilmiş görünüm ve dictionary bu maliyeti farklı aşamalara taşır. Doğru karar, sorgu sıklığı ve boyut değişikliklerinin hacmine bağlıdır.

Denormalizasyon, sık yapılan birleştirmeleri yazma anına taşıyarak okuma gecikmesini azaltabilir. Buna karşılık boyuttaki bir niteliğin değiştirilmesi tarihsel olayların yeniden yazılmasını veya sorguda güncel boyutun ayrıca kullanılmasını gerektirebilir. Örneğin müşteri segmenti sık değişirken olayın gerçekleştiği andaki segmentin saklanması ile bugünkü segmentinin raporlanması farklı bilgi gereksinimleridir. Karar, sorgu hızı yanında tarihsel doğruluk ve bakım maliyetiyle verilmelidir.

Boyut tablosunda günlük 1000 değişiklik olduğunu ve 200 milyon tarihsel olayın aynı özellikleri kopyalayarak saklandığını düşünelim. Geçmiş olayların kaynak düzeltmesi nedeniyle yeniden işlenmesi, yalnız 1000 boyut satırının güncellenmesinden farklı bir yazma maliyeti doğurur. Denormalizasyon, okuma sırasında kaçınılan JOIN maliyetini yazma, bakım ve geçmiş verinin yeniden üretimi maliyetine dönüştürür.

Güncel boyut değerleriyle raporlama isteniyorsa dictionary lookup veya sorgu zamanı JOIN uygun olabilir; olayın gerçekleştiği andaki boyut değeri korunacaksa immutable olgu üzerinde tarihsel sürüm ya da zamansal boyut JOIN'i gerekir. Incremental materyalleştirilmiş görünüm, yalnız tetikleyici kaynak INSERT'lerine tepki veriyorsa sonradan değişen boyut tablosu nedeniyle daha önce ürettiği sonucu otomatik güncellemez.

### 19.7. Bölütler Arası JOIN ve Dağıtık Birleştirme Semantiği

Bölütler arası JOIN her bölütün sağ taraf verisini görmesini gerektirebilir; GLOBAL JOIN belirli durumlarda ara tabloyu dağıtır. Ağ aktarımı, memory fanout ve eşzamanlı sorguların küme yükü hesaplanmadan dağıtık JOIN ölçeklenebilir kabul edilmemelidir.

Dağıtık JOIN'in yerel bölüt verisi üzerinde çalışması, her shard'da gerekli boyutun bulunduğu varsayımını gerektirebilir. `GLOBAL JOIN` benzeri stratejiler sağ taraf verisini düğümlere dağıtarak bazı eksik eşleşmeleri çözebilir, ancak ağ ve bellek maliyeti doğurur. Bölüt anahtarıyla JOIN anahtarının uyumu, veri hareketini azaltabilir. Tek düğümde hızlı olan bir sorgunun bölüt sayısı arttığında yavaşlaması çoğu kez verinin yanlış yerde birleşmesinden kaynaklanır.

## Ünite 20: Sorgu Planlama, Optimizasyon ve Paralel Yürütme

ClickHouse paralel yürütmede birden fazla okuma akışını filtreleme ve toplulaştırma işlemcilerine dağıtır; hızlanma son birleşme ve ortak kaynak sınırlarıyla sınırlanır.

![Paralel sorgu işlem hattı animasyonu](https://alikoker.com.tr/svg/parallel-query-pipeline.svg "Paralel sorgu yürütme")


ClickHouse SQL işlemleri yürütme hattındaki kaynak, dönüşüm ve sonuç operatörlerine ayrılır. Sorgu motoru bölünebilir iş parçalarını farklı CPU çekirdeklerinde çalıştırırken son aşamada birleştirme ve sıralama gerekebilir. Paralellik veri boyutundan bağımsız değildir: tek büyük veri parçası üzerinde okuma aralıklarının dağılımı ile çok sayıda küçük veri parçasının koordinasyonu farklı maliyet üretir.

Sorgunun toplam süresini düşürmek için en yavaş görünen işlemciyi optimize etmek her zaman doğru yöntem değildir; birçok işlemci paralel çalışır. Örneğin 16 worker aynı anda 1 saniye okuma yapıyorsa toplam 16 CPU-saniye ile geçen duvar saati 1 saniye olabilir. Daha sonra tek işçide 500 ms final toplulaştırma bulunuyorsa 16 ek çekirdek son aşamayı aynı oranda hızlandıramayabilir. `EXPLAIN PIPELINE` işlemcilerin dallanmasını, `system.query_log` gerçek sonuçları gösterdiğinden ikisi beraber incelenmelidir. Dağıtık sorguda bölütler arası dengesizlik, bir düğümde depolama gecikmesi veya skew diğer bütün düğümlerin tamamlanmasını bekletebilir. Sorgu optimizer'ın seçtiği join order ve pushdown stratejisi ancak fiilen okunan byte ve sonuç doğruluğuyla doğrulanır.

### 20.1. SQL Ayrıştırma, Anlamsal Çözümleme ve Mantıksal Plan

Parser SQL'i bir sözdizim ağacına ayırır; analyzer sütun/tabloları çözümler; planlayıcı uygulama sırasını ve operatör ilişkilerini kurar. Mantıksal eşdeğerlik fiziksel maliyet eşitliği değildir. Sorgunun nerede filtrelediği veya hangi tabloyu önce işlediği planla izlenir.

SQL parser sözdizimi ağacını üretir; analyzer adlandırma ve veri tiplerini çözer; logical plan veri akışında yapılması gereken ilişkisel işlemleri gösterir. Fiziksel plan bu işlemlerin hangi okuma, JOIN veya toplulaştırma algoritmalarıyla yürütüleceğini belirler. Sorgu metninin kısa olması fiziksel planın basit olmasını garanti etmez. Bir alt sorgunun beklenmedik biçimde büyük ara veri üretmesi ancak açıklama planı ve çalıştırma sayaçlarıyla görülür.

Sorgu planında yalnız operatörlerin sırası değil veri kardinalitesinin her operatörde nasıl değiştiği incelenir. `WHERE tenant_id = 42` seçiciliği %0,1 ise erken filtreleme bir milyar girişten yaklaşık bir milyon adayı bırakabilir; filtreyi pahalı bir `JOIN` sonrasına itmek ara veri ve hash maliyetini artırabilir. Ancak filtre, kullanılan sıralama anahtarına uymuyorsa diskte okunan granül miktarı aynı oranda azalmaz.

Planlanan ve fiili okuma miktarı farklı katmanlardan ölçülür: `EXPLAIN` hangi operatörlerin kurulacağını, `system.query_log` ve diğer tanılama araçları kaç satır/bayt okunduğunu ve ne kadar bellek harcandığını gösterir. Bu ayrım optimizer tahmininin iyi olmasına rağmen disk aktarım kapasitesinin yetersizliği nedeniyle gecikmenin yükseldiği senaryoları teşhis etmeyi sağlar.

### 20.2. EXPLAIN AST/PLAN/PIPELINE Çıktıları

`EXPLAIN AST` ayrıştırılmış sorgu yapısını, `EXPLAIN PLAN` planlayıcının operatörlerini, `EXPLAIN PIPELINE` ise işlemciler arasındaki yürütme akışını ve paralel kanalları gösterir. Bu çıktılar gerçek sorgu sürelerini ölçmez; indeks seçimi, ara sonuçların boyutu ve işlemci dağılımı hakkında sınanabilir hipotezler üretir.

```sql
EXPLAIN indexes = 1
SELECT service_id, count(), sum(bytes_sent)
FROM events
WHERE service_id = 42
  AND event_time >= toDateTime64('2026-10-27 00:00:00', 3, 'UTC')
  AND event_time < toDateTime64('2026-10-28 00:00:00', 3, 'UTC')
GROUP BY service_id;

EXPLAIN PIPELINE
SELECT service_id, count(), sum(bytes_sent)
FROM events
WHERE service_id = 42
  AND event_time >= toDateTime64('2026-10-27 00:00:00', 3, 'UTC')
  AND event_time < toDateTime64('2026-10-28 00:00:00', 3, 'UTC')
GROUP BY service_id;
```

İlk planın `PrimaryKey`/veri parçası aralıkları kaç granülün aday kaldığını açıklar; sorgu yürütülmeden 99% işaret elenmesi sonucuna varılması sorgunun toplamda 100 kat hızlandığını kanıtlamaz. Okunan sütun miktarı, bellekteki grup sayısı, birleştirme işlemleri ve işlemci kuyruklanması ayrıca etkili olabilir. İkinci plan akışında çok işlemci bulunması etkin paralel iş miktarı bulunduğunu garanti etmez: az sayıda veri parçası, dengesiz blok dağılımı veya tek bir final toplulaştırma aşaması paralelliği sınırlayabilir.

Gerçek yürütme, aynı sorguya ait `query_id`, `read_rows`, `read_bytes`, `memory_usage`, süre ve uygun `ProfileEvents` ölçüleriyle incelenir. Önbellek etkisini ayırmak için soğuk/sıcak koşullar ve arka plan birleştirme durumu kaydedilir. Plan metninin sürümler arasında birebir farklılaşması regresyonun tek başına kanıtı değildir; aynı sonuç kümesi ve aynı kaynak sınırları altında yapılan ölçüm belirleyicidir. [11, 16]

### 20.3. İşlem Hattında İşleyiciler, Bağlantı Noktaları ve Blok Akışı

İşlem hattı işlemcilerinin input/output portları blok akışını taşır; parallel stream'ler kısmi iş gerçekleştirebilir. Birleştirme, sort veya toplam durumların finalizasyonu bazı aşamaları daraltabilir. İşlemci sayısını artırmak veri dağılımı yetersizse anlamlı hızlanma sağlamaz.

Pipeline'daki bir kaynak işlemcisi bloklar üretir, dönüştürücü işlemciler bu blokların içeriğini değiştirir ve sonuç işlemcileri veriyi tüketir. Her işlemci eşzamanlı bütün iş parçacıklarında çalışmak zorunda değildir; `EXPLAIN PIPELINE` paralel kollara bölünmeyi gösterir. Örneğin kısmi hash agregasyonu yerel bloklarda yapılabilir, ardından farklı akışların durumları bir final aşamasında birleştirilebilir. Seri kalan son aşama çok sayıda çekirdeğin etkin hızlanmasını sınırlayabilir.

Sorgunun bir aşamasında sekiz akış bulunması, her aşamada sekiz CPU çekirdeğinin sürekli çalıştığı anlamına gelmez. `GROUP BY` son birleştirmesi, küresel `ORDER BY` ve sonuç aktarımı gibi daralma noktaları işlem hattı genişliğini azaltır. 26.10'daki yüksek yük altında işlem hattı daraltma yaklaşımı, aynı anda çok sayıda sorgu çalışırken her sorgunun gereğinden fazla iş parçacığı talep etmesini sınırlamayı hedefler. Eşzamanlı kullanıcı sayısı arttığında tek sorgu için en düşük gecikmeyi veren `max_threads` değerinin sunucu genelinde en yüksek işlem hacmini vermesi beklenmemelidir. Deneyde toplam etkin thread, context-switch oranı, p99 gecikmesi ve sorgu başına CPU zamanı birlikte izlenmelidir. [41]

### 20.4. Filtre İtme, Sütun Budama ve İfade Optimizasyonu

Predicate pushdown filtreyi veri kaynağına yakın uygular; projection gereksiz kolonları çıkarır; expression optimizasyonu yinelenen hesapları azaltabilir. Ancak filtre ifadesinin sütuna uygulanan bir fonksiyon olması indeks budamasını zorlaştırabilir. Dönüşümler sorgu planıyla doğrulanır.

Predicate pushdown filtrenin veri kaynağına daha yakın uygulanmasını hedefler; sütun pruning yalnız kullanılan sütunları okur. Bir fonksiyonun `WHERE toDate(event_time) = ...` biçiminde yazılması ile doğrudan zaman aralığı karşılaştırması her sorgu planında aynı veri atlama sonucunu vermeyebilir. Fiziksel sıra ve fonksiyonun monotonluğu budama imkanını etkiler. `EXPLAIN` planı ve okunan işaret sayısı, SQL ifadesinin beklendiği gibi optimize edilip edilmediğini gösterir.

26.10'daki tarama sırasında metin filtresi uygulaması, `LIKE` ve `startsWith` gibi koşullarda eşleşmeyen dizgelerin gereksiz kopyalanmasını azaltır. Resmi tanıtımdaki bir örnekte en yüksek bellek tüketimi 275 MB'tan 5 MB'a inmiştir. Söz konusu iyileşme, filtreden geçen satır oranına ve kaynak formatının çözümleme yoluna bağlıdır; sonuç kümesinin tamamı eşleşiyorsa tarama sırasında filtreleme ek yük doğurabilir. Ayrı bir Top-K optimizasyonu, `GROUP BY` ve sıralı `LIMIT` için eşik değerini okuma aşamasına geri ileterek sonraki sütunların gereksiz okunmasını önleyebilir. Sunumdaki örnekte okunan veri 9,45 GB'tan 144 MB'a düşmüştür. Bu, birincil anahtar/minmax ile atlanabilecek granule'lerin bulunduğu iş yükleri için geçerlidir. [41]

### 20.5. Paralel Okuma, Toplulaştırma ve Veri Değişimi

Yerel kısmi GROUP BY, bölütlerin özet durumlarını küçültür; final toplulaştırma bunları toplar. Grup kardinalitesi çok yüksekse ara durumlar ve memory önemli miktarda büyüyebilir. Her bölütün kendi LIMIT sonucunu döndürmesi global TOP-K doğruluğu için yeterli olmayabilir.

Yerel `GROUP BY` işlemlerinde her okuma hattı kendi kısmi hash tablosunu oluşturabilir; final birleşim maliyeti farklı anahtar sayısıyla büyür. Bölütler arası sorguda yalnız kısmi durumların taşınması, ham olayları ağ üzerinden toplamaya göre verimli olabilir. Ancak grup anahtarı her olay için farklıysa gönderilen ara sonuç yaklaşık ham satır sayısına yaklaşır. Ağ aktarımı ve serializer CPU'su ayrıca ölçülmeden çok düğüm sayısının doğrusal hızlanma sağlayacağı varsayılamaz.

Dağıtık sorgu planında yalnız bölüt sayısına bakarak hızlanma hesabı yapılamaz. Büyük bir `GROUP BY` için yerel kısmi agregasyonların sonucu ağ üzerinden toplandığında taşınan veri miktarı, ara grupların kardinalitesine bağlıdır. ClickHouse 26.8'de duyurulan maliyet temelli dağıtık plan optimizasyonu; JOIN, agregasyon, sıralama ve veri hareketi için kardinalite tahminlerini kullanmayı amaçlar. Tahmin hatası nedeniyle planlanan küçük tarafın gerçekte büyük olması bellek taşmasına ve ağda geniş çaplı dağıtık veri değişimi işlemine yol açabilir. Dolayısıyla tek düğümlü `EXPLAIN` sonucuyla küresel trafik hakkında kesin hüküm verilmez; her bölütün okunmuş baytları ve ağ taşımaları birlikte değerlendirilir. [46]

### 20.6. SIMD, Çok Çekirdekli İşleme, JIT ve Çok Düğümlü Yürütme

Çekirdek içindeki vektörleştirme, SIMD ve belirli durumlarda JIT farklı optimizasyon katmanlarıdır. Kullanılan yol işlemci bayraklarına, veri tiplerine ve sorgu fonksiyonlarına bağlıdır. Çok düğümlü yürütmede ağ ara sonuç aktarımı yeni bir maliyet boyutu oluşturur.

SIMD aynı çekirdekte çok sayıda sayısal elemanı işler, multicore farklı görevleri fiziksel çekirdeklere dağıtır, çok düğümlü yürütme ise ağ üzerinden veri veya ara sonuç değişimini gerektirir. Bu üç paralellik düzeyinin maliyetleri aynı değildir. JIT derleme kullanılabilen bazı işlemlerde tekrar eden ifadeler üzerinde kod üretiminin başlangıç maliyeti vardır; bütün ClickHouse sorgularının JIT ile çalıştığı kabul edilmemelidir. İş yükü için gerçek paralellik sorgu planından ve CPU kullanımından ölçülür.

### 20.7. Maliyet, Hızlanma Sınırları ve İş Yükü İzolasyonu

Bir sorgu ayrılan `max_threads` kaynaklarıyla hızlanırken sistemdeki eşzamanlı diğer sorguların kuyruk gecikmesi artabilir. İşlem hacmi ve p99 gecikme farklı optimizasyon hedefleridir. İş yükü isolation, memory quotas ve concurrency limits birlikte tasarlanır.

Servis katmanındaki eşzamanlılık, kaynak doygunluğu ve veri erişim bütçesi [Java Tabanlı Veri Sistemlerinde Yüksek Başarım](/java-tabanli-veri-sistemlerinde-yuksek-basarim) kapsamında ele alınır.

Tek sorgunun yürütme süresi, iş yükünün sürdürülebilirlik kapasitesinden ayrılır. Örneğin tek sorgu süresi 80 ms ve her sorgu ortalama 2 CPU-saniyesi tüketiyorsa sekiz çekirdekli sunucu yalnız işlemci sınırına göre en fazla yaklaşık 4 sorgu/saniye sürdürebilir; bellek ve disk daha erken sınır oluşturabilir. Bu sayılar örnek bir kaynak modelini açıklar. Aynı sorgu paralel yürütmeyle duvar saatinde hızlı tamamlanabilir ama çekirdek zamanı pahasına daha az concurrency kapasitesi bırakabilir.

Amdahl yaklaşımında seri bölüm oranı `s`, çekirdek sayısı `p` ise ideal hızlanma `S(p)=1/[s+(1−s)/p]` ile sınırlanır. `s=0,05` ve `p=32` için hızlanma yaklaşık 12,5 kattır; 32 kat değildir. Gerçek dağıtık yürütmede ağ dağıtık veri değişimi ve senkronizasyon yükü üst sınırı daha da düşürür. Çok büyük `max_threads` seçimi aynı sistemdeki diğer sorguların kuyruğunu uzatabilir. Bu sebeple sorgu gecikme ile aggregate işlem hacmi birlikte optimize edilir.

### 20.8. Sorgu Planı Üzerinden Darboğaz Teşhisi

Yavaş sorguda önce okunan satır/bayt, işaret oranı, bellek zirvesi, JOIN boyutu, external diske taşma, disk işlem hacmi ve dağıtık ağ hacmi incelenir. `EXPLAIN` ile gerçek `system.query_log` ölçümleri ayrı delillerdir; planı okumak tek başına darboğazın gözlendiği anlamına gelmez.

Bir sorgu yavaşsa önce okunan satır/bayt, seçilen işaret, ara grup sayısı, hash JOIN build boyutu ve sonuç satır sayısı ayrıştırılır. Disk I/O doygunluğu varsa sıralama anahtarı/filtre düzeni, bellek baskısı varsa kardinalite ve sorgu algoritması incelenir. CPU doygunluğunda sıkıştırma açma, ifade değerlendirme veya metin işleme maliyeti ayrı profil edilmelidir. Sadece `max_threads` artırılarak bütün darboğazların çözüleceği varsayımı yanlıştır.

## Ünite 21: Materyalleştirilmiş Görünümler, Projeksiyonlar ve Ön Hesaplama

Ön hesaplama, her sorguda aynı toplamayı yeniden yapmak yerine maliyeti veri alma zamanına taşır. Kazanç, ek yazma maliyeti ve depolama büyütmesiyle birlikte değerlendirilir.

![Materyalleştirilmiş görünüm ön hesaplama animasyonu](https://alikoker.com.tr/svg/materialized-view-precompute.svg "Materyalleştirilmiş görünüm ve ön hesaplama")


Materyalleştirilmiş görünüm, INSERT anında veya belirlenmiş yenileme takviminde hesaplama maliyetini sorgudan veri hazırlama aşamasına taşıyabilir. Projection ise kaynak tabloya bağlı alternatif fiziksel düzen veya agregasyon yapısıdır; optimizer tarafından otomatik seçilebilir. Ön hesaplama veri tazeliği, düzeltme olayları ve yeniden işleme konusunda yeni doğruluk sorumlulukları doğurur.

Materyalleştirilmiş görünüm tasarımında kaynak INSERT'in başarılı olduğu anda hangi hedeflerin üretildiği ve hangi hatanın hangi aşamada raporlandığı incelenmelidir. Örneğin olaylar saniyede yüz bin kez geliyorsa her farklı gösterge paneli sorgusunu önceden hesaplamak yazım bütçesini hızla tüketebilir. Sık kullanılan dakikalık histogram, servis başına toplam ve nadiren kullanılan ayrıntı sorgusu farklı materyalleştirme stratejileri gerektirir. Refreshable view belirli zamanlarda tam sorgu çalıştırırken incremental MV kaynağa gelen INSERT bloklarını işlemesiyle ayrılır; bunların geçmiş UPDATE/DELETE karşısındaki doğruluk modelleri eşit değildir. Projection aynı tablonun optimizer tarafından kullanılabilecek alternatif düzenini tutar; bir uygulama denormalizasyon hedef tablosuyla aynı işletim yüzeyine sahip değildir. Seçim maliyeti sorgu başına okuma kazancı ile kaynak başına ek yazma/birleştirme giderini birlikte içerir.

### 21.1. Normal ve Materyalleştirilmiş Görünümlerin Semantiği

Normal VIEW sorgu tanımını saklar ve okuma anında yürütür. Incremental materyalleştirilmiş görünüm kaynak INSERT bloklarını dönüştürüp hedefe yazar; geçmiş tablo satırlarının sonradan değişmesi otomatik ve sınırsız yeniden hesaplama garantisi değildir. Bu fark CDC ile çalışan tasarımlarda kritiktir.

Normal view, çoğu durumda saklanmış sorgu tanımıdır; sonuç veri değiştikçe yeniden hesaplanır. Materyalleştirilmiş görünüm ise tanımlanan dönüşümü sonuç verisi olarak saklayabilir veya yenileme stratejisine göre yeniden üretir. Aynı SQL'in view ve MV üzerinden çalışması tazelik ve kaynak tüketimi bakımından farklıdır. ClickHouse'taki incremental MV, kaynak tabloda geçmişte yapılan tüm değişikliklerin kendiliğinden yansıtıldığı tam CDC mekanizması olarak görülmemelidir.

### 21.2. Artımlı ve Yenilenebilir Materyalleştirilmiş Görünümler

Incremental MV düşük gecikmeli akış özetleri için uygundur; refreshable MV belirli aralıkta sorgu sonucunu yeniden üretebilir. Refresh maliyeti kaynak veri hacmine ve sorguya bağlıdır. Tazelik hedefiyle tam yeniden hesaplama maliyeti birlikte değerlendirilir.

Incremental materyalleştirilmiş görünüm tipik olarak yeni eklenen bloklara dönüşüm uygular; geçmiş kaynak tablonun bütün değişikliklerini otomatik olarak yeniden hesaplayacak genel bir mekanizma olarak görülmemelidir. Refreshable materyalleştirilmiş görünüm belirli aralıkta tam sorgu sonucunu yeniden üretebilir. Birincisi düşük gecikmeli özet güncellemede yararlı olabilirken ikincisi kaynak JOIN'lerinin değiştiği veya dönemsel yenilemenin uygun olduğu durumda tercih edilebilir. Yenilemenin çalışmadığı aralıkta istemciye gösterilecek veri yaşı açıkça tanımlanmalıdır.

Incremental materyalleştirilmiş görünüm (MV), kaynak tablodaki her yeni INSERT bloğunu bir dönüşümden geçirir; kaynak tablonun tamamını düzenli olarak baştan tarayan bir görünüm değildir. Hedef tabloya önceden hesaplanmış sonuçların aktarılması, okuma anındaki CPU maliyetini azaltabilir ancak aynı dönüşüm her INSERT'te çalışır. Kaynakta yapılan DELETE, UPDATE veya yeniden yazım, incremental görünümün hedefindeki geçmiş sonuçları otomatik düzeltmez. JOIN içeren görünümde yalnız sol kaynak tabloya gelen yeni bloklar tetiklenir; sağdaki boyut tablosunun değişmesi geçmiş çıktıyı kendiliğinden yenilemez.

Özetlerin yeniden hesaplanması gerekiyorsa materyalleştirilmiş görünüm ile ham veri üzerinde ayrı bir refresh mekanizması veya düzeltme olaylarının muhasebesi kurulmalıdır. `REFRESH EVERY` yaklaşımının sorguyu yeniden çalıştıran semantiği, incremental INSERT tetikleyicisinden farklıdır. İki yöntemi aynı tabloda yalnız isim benzerliğine dayanarak eşdeğer saymak doğru değildir. Kaynak: https://clickhouse.com/blog/10-best-practice-tips

ClickHouse 26.9 ile yenilenebilir materyalleştirilmiş görünüm tanımına eklenen `APPEND INCREMENTAL`, yalnız yeni onaylanmış kaynak bloklarını bir sonraki periyodik yenilemede işleyebilir. Kaynaktaki blok numarası ve blok içi ofset bilgilerinin korunması gerekir; aksi halde yalnız son çalışmadan beri eklenen kayıtların belirlenmesi garanti edilemez. Düz, eklemeli olay tablosunun periyodik dışa aktarımı için uygun olmakla birlikte UPDATE/DELETE ile geçmişin değiştiği veri kümelerinde düzeltme mantığı ayrıca tasarlanmalıdır.

Klasik incremental MV, INSERT sırasında blokları hedefe dönüştürürken periyodik `APPEND INCREMENTAL` yenileme ayrı bir yürütme zamanına sahiptir. Yeni verinin görünürlük gecikmesi yenileme periyodu, işleme süresi ve başarısız yenilemeden sonraki yeniden çalışma davranışına bağlıdır. Hedef tablo satır tekrarını önlemek için kaynak blok işaretleyicilerinin ve dış sistemin idempotency semantiğinin uyumlu olması gerekir. Kaynak: https://clickhouse.com/blog/clickhouse-release-26-09.

### 21.3. APPEND, REPLACE ve Zincirleme Görünümler

Cascading MV bir MV çıktısını başka bir MV'nin girdisi yapabilir. APPEND/REPLACE davranışı sürüme ve view türüne bağlıdır. Aynı olay yeniden beslendiğinde iki aşamada mükerrer toplulaştırma yaratılmaması için idempotency tasarlanır.

Cascading materyalleştirilmiş görünüm zinciri dönüşümleri aşamalı ayırabilir; ancak her aşamanın teslim ve hata politikası ayrıca düşünülmelidir. Zincirde ilk dönüşümün yeni veriyi alması sonraki hedefin tüm ara sonuçları eşzamanlı olarak yansıttığı anlamına gelmez. `APPEND` ve `REPLACE` türündeki yenileme davranışları kullanıldığı sürümde kesinleştirilmelidir. Tek bir özet tablosunun farklı bağımlılıklardan beslendiği durumlarda birleştirilebilir durumlar ve tekrar oynatma anahtarları önemlidir.

Zincirleme incremental materyalleştirilmiş görünüm tasarımında ilk aşama kayıtları dönemsel özetlere, ikinci aşama bu özetleri daha geniş dönemlere taşıyabilir. İlk aşamanın tekrar teslim aldığı bir olay ikinci aşamada da yinelenen katkı üretebilir. Her aşama için kaynak blok kimliği, deduplication davranışı ve hedef tablo motorunun birleştirme semantiği ayrı doğrulanmalıdır.

Örnek: kaynaktan dakikalık sayım, dakikalıktan saatlik sayım oluşturuluyorsa ikinci aşama `count()` ile dakika satırlarını saymak yerine dakika sayımlarının toplamını hesaplamalıdır. Kaynaktaki gecikmiş olay bir önceki dakika için yeni veri parçası oluşturduğunda zincir aynı döneme ikinci katkı ekleyebilir; bu durum amaçlanan toplam hesabıyla uyumludur, fakat olay yeniden oynatımından gelen gerçek mükerrer kayıt ayırt edilmelidir.

### 21.4. Toplulaştırma Durumları ve Summing/Aggregating Birleştirmeleri

`AggregatingMergeTree` toplulaştırmanın ara durumlarını saklayabilir. `countState`, `avgState` ve `uniqState` gibi fonksiyonlar, fiziksel birleştirmeler henüz gerçekleşmese bile okuma sırasında karşılık gelen `-Merge` combinator'leriyle birleştirilir. Birden çok saatin ortalamalarını doğrudan ortalamak doğru değildir; bütün gözlemlere karşılık gelen toplam ve sayım ya da `avgState` korunmalıdır.

```sql
CREATE TABLE hourly_event_stats
(
    bucket DateTime('UTC'),
    service_id UInt32,
    event_count AggregateFunction(count),
    duration_avg AggregateFunction(avg, UInt32)
)
ENGINE = AggregatingMergeTree
PARTITION BY toYYYYMM(bucket)
ORDER BY (service_id, bucket);

CREATE MATERIALIZED VIEW hourly_event_stats_mv
TO hourly_event_stats AS
SELECT
    toStartOfHour(event_time) AS bucket,
    service_id,
    countState() AS event_count,
    avgState(duration_ms) AS duration_avg
FROM events
GROUP BY bucket, service_id;

SELECT
    service_id,
    bucket,
    countMerge(event_count) AS n,
    avgMerge(duration_avg) AS average_duration
FROM hourly_event_stats
GROUP BY service_id, bucket;
```

Artımlı materyalleştirilmiş görünüm, yalnız kurulduktan sonra kaynak tabloya gelen INSERT bloklarını işler. Önceden var olan kayıtlar için geçmiş veri yüklemesi ayrı yürütülür; aynı kayıt aralığının canlı ingest ile kesişmesi özet tabloda çift sayım yaratır. Cutover kesiti veri kaynağının anlık görüntü/CDC ilerleme bilgisine bağlanmalı, geçmiş veri aktarımının tamamlanması kaynak–hedef toplamlarıyla sınanmalıdır. `POPULATE` kullanımı tek başına eşzamanlı yazma penceresini kapatan bir işlem protokolü değildir.

Arka plan birleştirmeleri aynı `(service_id,bucket)` anahtarına ait state satırlarını fiziksel olarak birleştirebilir, fakat sorgu sonucu `countMerge` ve `avgMerge` ile hesaplanmalıdır. Kaynak kayıtta UPDATE veya DELETE varsa hedefe geçmişte yazılmış agregasyon state'i kendiliğinden tersine çevrilmez. Düzeltme stratejisi sürümlü olay modeli, telafi edici kayıtlar veya ilgili pencerenin kontrollü yeniden hesaplanması arasında seçilir. Analitik doğruluk, her servis–saat penceresi için kaynakla elde edilen sayım ve ortalamanın hedefteki sonuçla karşılaştırılmasıyla sınanır. [12]

### 21.5. Materyalleştirilmiş Görünümlerle Asenkron İşlem Güvenliği

MV zincirlerinde kaynak tablodaki tekrar engellenmiş olsa bile hedef özetin tam olarak bir kez değiştiği otomatik varsayılamaz. Hangi aşamada INSERT başarılı, başarısız veya yeniden denenmiş olduğuna göre idempotency testi yapılmalıdır. Hedef tabloya ait bölüm ve aggregator anahtarları bu kararda rol oynar.

İşlem hattı en az bir kez teslim garantisi sunuyorsa materyalleştirilmiş görünüm hedefinde tekrar eden ekleme görülebilir. Sadece kaynak tabloda blok tekilleştirmesinin etkin olması, çok katmanlı zincirin bütün yan etkilerini idempotent yapmaz. Hedef ölçü hesabında doğal olay kimliği veya CDC işlem konumu korunarak tekrarların ayıklanabileceği bir veri modeli kurulmalıdır. Offset işlem onayı'i, ClickHouse ekleme onayı ve hedef view dönüşümünün gerçekleşme sırası ayrı hata noktalarıdır.

Asenkron INSERT ve bağlı incremental materialized view'lerde deduplikasyonun kapsamı sürüme bağlıdır. ClickHouse 26.1 sürüm notları, daha önce kaynak tabloda yinelenmeyi önleyen mekanizmanın view hedefinde aynı yeniden denemeye rağmen tekrar yazım üretebildiğini; 26.1 ile view işleme aşamalarında da deduplikasyonun eşgüdümlü uygulandığını belirtir. Bu özellikten yararlanmak için ilgili ayarların, insert token politikasının, tekrarlama penceresinin ve kullanılan tablo motorunun aynı testte sınanması gerekir. Kaynak: https://clickhouse.com/blog/clickhouse-release-26-01

Deduplikasyon penceresi dolduktan sonra gelen aynı olayın tam olarak bir kez yazılacağı kendiliğinden garanti değildir. İş düzeyindeki mantıksal tekillik için kaynaktan gelen kararlı olay kimliği veya CDC işlem konumu üzerinden yeniden işleme sözleşmesi gerekir. INSERT deduplikasyonu ile olayların işsel anlamda tekilleştirilmesi farklı katmanlardır.

26.3 LTS sürümünden itibaren asenkron INSERT varsayılan olarak etkinleştirilmiştir. Bunun anlamı her tek satırlık isteğin ayrı bir MergeTree veri parçasını oluşturma zorunluluğunun ortadan kalkmasıdır; sunucu tamponlama ve flush işlemini üstlenir. Ancak istemcinin başarı yanıtını hangi aşamada aldığı `wait_for_async_insert` ayarına bağlıdır. `wait_for_async_insert=1` etkinliğinde kabul onayı flush sonrasına ertelenebilir; `0` durumunda tamponlanmış fakat kalıcı hale gelmemiş veri için erken onay söz konusudur.

Güvenilir veri aktarımında kayıtların kaybolmaması kadar yinelenmemesi de önemlidir. Timeout sonrası tekrar gönderim ile sunucuda başarılı yazımın aynı anda gerçekleştiği belirsizlik durumunda istemci, yalnız yanıt koduna bakarak “bu olay kesinlikle yazılmadı” kararını veremez. Yeniden oynatılabilir kaynak offset'i, deduplication davranışı ve uçtan uca sayım doğrulaması birlikte tasarlanmalıdır. 26.1 ile materyalleştirilmiş görünüm içeren asenkron yazımlarda deduplication kapsamı geliştirilmiştir; önceki sürümlerdeki koşullar aynen taşınmamalıdır.

Asenkron INSERT varsayılanının değiştiği sürüm ClickHouse 26.3 LTS, materyalleştirilmiş görünüm deduplikasyonunun geliştirilmesi 26.1 olarak belgelenmiştir: https://clickhouse.com/blog/clickhouse-release-26-03.

### 21.6. Projections ve Otomatik Seçim

Projection tablonun sorting key'inden farklı düzende fiziksel veri saklayarak alternatif filtre ve gruplama yolları sunabilir. Uygun plan bulunursa optimizer projection seçer; kullanıcı her zaman zorunlu seçim yapmaz. Materyalleştirme, disk ve INSERT maliyeti hesaplanır.

Projection, ana tablonun verisine farklı bir fiziksel erişim veya ön toplulaştırma düzeni sağlayabilir; sorgu optimizer'ı koşullar uygunsa projection'dan yararlanabilir. Materyalleştirilmiş görünüm ise ayrı bir hedef tabloya veya dönüştürülmüş veri akışına ilişkin açık bir mimari sözleşmedir. Projection sorgudan bağımsız ikincil şema tanımına yakındır; materyalleştirilmiş görünüm ayrı yaşam döngüsü ve sorgulama modeli sağlar. Her ikisi de saklama, güncelleme ve birleştirme maliyeti üretir.

Bir sorgu `WHERE tenant_id=42 AND event_time BETWEEN ...` biçimindeyse ana tablo `ORDER BY(event_time, tenant_id)` düzeninde olabilir; `ORDER BY(tenant_id,event_time)` düzenli projection, uygun koşullarda daha az granül okunmasını sağlayabilir. Optimizer'ın projection'ı seçmesi garanti değildir. `EXPLAIN` planı, okunan bytes ve sorgu log karşılaştırılmalıdır. Projection artışı her sorguya değil, yalnız tanımlandığı sorgu ailesine karşılık gelir; disk alanı ve ingest maliyetiyle ölçülür.

### 21.7. _part_offset Tabanlı Projeksiyonlar

`_part_offset` kullanan hafif projection türleri alternatif anahtarı ve kaynak veri parçası içi konuma başvuruyu depolayabilir. Bu tasarım tüm kolonların kopyasını tutmadan ikincil erişim yaratabilir; performans sorgu pattern ve hedef sürüme bağlıdır.

Hafif projection'ın `_part_offset` üzerinden asıl veri parçası satırına dönmesi, indeksten bulunan konumun bütün hedef sütunları içermemesine benzer. Eğer sorgu sadece projection'da bulunan alanlarla karşılanabiliyorsa ek okuma azalabilir; geniş bir SELECT asıl veri parçasına sık geri dönüş gerektirebilir. Alternatif sıralama anahtarının seçiciliği, projection oluşturma maliyeti ve birleştirme sırasında güncelleme işi birlikte hesaplanmalıdır. Bu özellik sürüme özgü olduğundan üretimde etkinleştirmeden önce hedef sürümün belgelerine bakılmalıdır.

İkincil indeks benzeri projection düzenlerinde `_part_offset` verinin ikinci tam kopyasını saklamak yerine alternatif sıralama anahtarı üzerinden temel veri parçası içindeki satırlara dönüş imkanı sağlar. Bunun bedeli dolaylı veri erişimidir: alternatif anahtarla yoğun eşleşen fakat temel tablonun `ORDER BY` düzeninde dağınık kayıtlar bulunduğunda çok sayıda granül okunabilir. Dolayısıyla projection boyutunun küçülmesi her sorguda daha düşük gecikme demek değildir.

ClickHouse 25.6 ve 26.1 döneminde projection temelli ikincil indeksleme ve çoklu indeks kullanımında değişiklikler yapılmıştır. İlgili sürümde granül düzeyinde budama olup olmadığı ve planner'ın hangi projection'ı seçtiği `EXPLAIN indexes=1` ile kontrol edilir. Kaynak: https://clickhouse.com/blog/projections-secondary-indices.

### 21.8. Materyalleştirilmiş Görünüm ve Projection Karşılaştırması

MV dış hedef tabloda farklı veri akışı semantiği oluşturur; projection kaynak tablonun depolama yapısıyla bütünleşir. Sorgu rewrite, tarihsel geçmiş veri yüklemesi ve operasyonel görünürlük bakımından farklıdır. Benzer sorgu hızlanması olası olsa da bakım maliyeti eşit değildir.

Projection aynı tablonun alternatif fiziksel düzenini veya ön hesaplanmış görünümünü tutabilir ve optimizer tarafından seçilebilir. Materyalleştirilmiş görünüm ise ayrı hedef tabloya dönüşüm taşıyarak daha açık veri yaşam döngüsü tasarımına olanak sağlar. Projection'ın seçiminde optimizer ve sorgu planı, MV'de ise uygun hedef tablonun kullanılması belirleyicidir. Her iki mekanizma da fazladan disk alanı, INSERT maliyeti ve yeniden oluşturma işi üretir. Aynı sorgu ailesi için net fayda başarım karşılaştırması ile ölçülür.

### 21.9. Geçmiş Veri Yükleme, Mükerrer Kayıtlar ve Yeniden İşleme Doğruluğu

Yeni MV var olan geçmiş veriyi otomatik olarak güvenli ve eksiksiz geriye dönük işlemez. Geçmiş veri yüklemesi sırasında yazılan yeni olaylarla çakışma ve yeniden oynatım planlanmalıdır. Eski dönem özetlerinin ne zaman ve hangi snapshot'tan üretildiği belirlenir.

Materialized view'ı kaynak tabloya sonradan eklemek geçmiş satırların tamamının yeni hedefe aktarıldığını garanti etmez. Geçmiş veri yüklemesi sırasında yeni akışın eşzamanlı gelmesi çift sayım veya boşluk oluşturabilir. Güvenli yaklaşım, zaman/SCN gibi sınırla eski ve yeni veri akışlarını ayırmak ve iki taraftaki özetlerin birleşiminde tam kapsama sağlamaktır. `countState`, `uniqState` gibi agregasyon durumlarının doğru birleştirilmesi, nihai skalerleri körlemesine toplamaktan farklıdır.

Yeni bir materyalleştirilmiş görünüm mevcut büyük veri kümesine sonradan eklendiğinde tarihsel veri parçalarının kendiliğinden hedefe taşındığı varsayılamaz. Kesintisiz geriye dönük doldurma için bir eşik anı belirlenir: örneğin olay zamanı `t < T` olan geçmiş veri ayrı `INSERT INTO target SELECT ...` ile yüklenirken `t ≥ T` olan yeni veriler görünüm üzerinden alınır. Ancak geç gelen olaylar ve olay zamanı üzerinden bölme bu iki kümeyi yanlış sınırlandırabilir. Güvenli kesme noktası, kaynak sistemin değişmez ingest pozisyonu ya da desteklenen anlık görüntü/akış işleme kesitiyle kurulmalıdır.

Aynı kayıt hem geçmiş veri yüklemesi hem akış yolunda işlenirse özet tabloda toplama iki kez gerçekleşebilir. Deduplikasyon ham tabloda gerçekleşse dahi view hedefinin semantiği ayrıca doğrulanmalıdır. Düzeltme için hedef tabloyu tam yeniden kurmak gerekebilir; bu durumda yeni hedefe hesaplama ve sonuç mutabakatı tamamlandıktan sonra okuyucuların yönlendirilmesi daha güvenilir bir operasyon desenidir.

### 21.10. Yazma Büyütmesi, Veri Alımı Maliyeti ve Sorgu Kazancı

Bir INSERT'in maliyeti kaynak veri parçaları yanında her projection veya MV hedefi için ek hesaplama ve depolama doğurabilir. Kullanılan sorgunun sıklığı düşükse okuma kazancı sürekli yazma maliyetini karşılamayabilir. Sorgu başına toplam maliyet iş yükü ağırlıklarıyla değerlendirilir.

Bir veri parçası içinde ek projection oluşması veya MV hedefi için yeni verinin işlenmesi, kaynak INSERT onayını ve background birleştirme maliyetini etkileyebilir. Sorgularda kazanılan CPU saniyesi ile veri alımında harcanan ek CPU/disk kaynakları birlikte değerlendirilmelidir. Çok sayıda nadir kullanılan MV oluşturulması, okuma hızına az katkı sağlarken her eklemede düzenli sabit maliyet getirebilir. Analitik tablonun bakım maliyeti sorgu başına değil toplam iş yükü için hesaplanmalıdır.

## Ünite 22: Veri Güncelleme, Silme ve İşlemsel Tutarlılık

ClickHouse güncelleme ve silme davranışı klasik satır-içi OLTP güncellemesine benzemez. Mantıksal görünürlük ile fiziksel yeniden yazım farklı zamanlarda gerçekleşebilir.

![Mutation patch ve okuma görünürlüğü animasyonu](https://alikoker.com.tr/svg/mutation-patch-final.svg "Mutation patch ve okuma görünürlüğü")


ClickHouse UPDATE ve DELETE destekler; ancak OLTP sistemlerinde çok sayıda kısa işlem için beklenen satır kilitleme, referans bütünlüğü ve çok tablolu işlemsel davranışla birebir eşdeğer değildir. Klasik mutation büyük data veri parçalarını yeniden yazabilir; daha yeni hafif güncellemeler değişiklikleri patch veri parçası olarak tutup okumada uygulayabilir. Hangi yaklaşımın uygun olduğu değişen satır oranına ve beklenen sorgu gecikmesine bağlıdır.

Geleneksel mutation, filtreye uyan satırları içeren veri parçaları'ları yeniden yazabilir; dolayısıyla fiziksel yazma maliyeti güncellenen satır adedinden büyük olabilir. Hafif UPDATE patch veri parçası yaklaşımı küçük değişikliklerde bu maliyeti geciktirir veya azaltır; okuma sırasında patch uygulama bedeli doğurur. Bu iki mekanizma farklı iş yüklerinde tercih edilmelidir. `DELETE` komutunun sorguda kaydı gizlemesi ile diskten ve yedekten imha edilmesi farklı zaman çizgileridir. İşlemsel sisteme özgü çok tablolu işlem gereksinimi varsa OLTP kaynak sistem yetkili kayıt noktası olmaya devam etmelidir. Son durum ve değişiklik geçmişi tablolarını ayrı tutmak, analitik sorgulara hem tarihsel hem güncel görünüm kazandırabilir; ancak CDC olaylarının işlem onay sırası ve kimliği doğru taşınmalıdır.

### 22.1. ALTER UPDATE/DELETE ve Değişiklik İşlemleri

`ALTER TABLE events UPDATE ... WHERE ...` ve `ALTER TABLE ... DELETE WHERE ...` klasik mutation iş yüküdür. Veri parçası yeniden yazımı kaynak tüketebilir; mutation asenkron ilerleyebilir. `system.mutations` durumuna bakılmadan komutun gönderilmesi fiziksel değişikliğin tamamlandığını kanıtlamaz.

Klasik `ALTER TABLE ... UPDATE/DELETE` mutation'ları eski veri parçası verisini yeniden yazarak maliyet yaratabilir. Mutation'ın kabul edilmesi, tüm veri parçalarının aynı anda dönüştürüldüğü anlamına gelmez; tamamlanma durumu `system.mutations` üzerinden izlenebilir. Tek bir milyonlarca satırlık eski partition'da düşük oranlı güncelleme bile çok büyük veri hareketi gerektirebilir. Bu nedenle sık noktasal güncelleme isteyen iş yükü için satır sürümleme veya kaynakta OLTP saklama seçenekleri karşılaştırılmalıdır.

### 22.2. Hafif DELETE, Yama Parçaları ve Yeni UPDATE

`DELETE FROM ... WHERE ...` hafif silmede satır görünürlüğü bir silme maskesiyle değişebilir; fiziksel baytın hemen yok edilmesi aynı şey değildir. Yeni `UPDATE` sözdizimi patch veri parçaları ve birleştirme sırasında materyalleştirme kullanabilir. Bu özelliklerin olgunluğu ve erişilebilirliği sürüm ayarlarıyla doğrulanır.

Mantıksal silme örneği:

```sql
DELETE FROM events
WHERE event_time < toDateTime64('2025-01-01 00:00:00', 3, 'UTC');
```

Bu komutun çalıştırılmasıyla bütün eski bytes'ın hemen imha edildiği varsayılmaz. Bölüm ölçeğindeki retention daha uygun olduğunda TTL ve DROP Bölüm seçenekleri değerlendirilir.

ClickHouse'un klasik `ALTER TABLE ... UPDATE/DELETE` mutasyonları veri part'larının etkilenen bölümlerini yeniden yazma maliyeti doğurabilir. SQL tarzı daha hafif UPDATE yaklaşımı patch veri parçaları yardımıyla özgün veri parçasını tümden yeniden yazmak yerine değişiklikleri ayrı yapı olarak saklayabilir; sorgu sırasında güncel değerlerin birleştirilmesi gerekir. Sık veya yoğun düzeltme iş yükünde patch veri parçası sayısı, okuma gecikmesi ve sonradan birleşme maliyeti göz ardı edilmez. `DELETE FROM` ile lightweight deletion mantıksal görünürlük ile fiziksel diskten silinme zamanını ayırabilir; kişisel veri silme gereksinimi için fiziksel imha sürecinin tamamlanması ayrıca doğrulanmalıdır.

ClickHouse'un 7 Ağustos 2025 tarihli üretici benchmark'ında yeni SQL UPDATE yaklaşımının, karşılaştırılan klasik mutasyon iş yüklerinde **1000 kata kadar** hızlı olduğu belirtilmiştir. Bu sayı patch-veri parçası UPDATE ile aynı ClickHouse ürününün eski mutation yaklaşımına ilişkin test sonucudur; ClickHouse'un her UPDATE sorgusunda PostgreSQL'den bin kat hızlı olduğu anlamına gelmez. Kaynak: https://clickhouse.com/blog/updates-in-clickhouse-3-benchmarks

Lightweight DELETE satırları mantıksal olarak görünmez kılabilir; fiziksel baytların ne zaman geri kazanıldığı arka plan birleşme ve temizlik davranışına bağlıdır. Patch-veri parçası tabanlı hafif UPDATE, küçük değişikliklerin geniş veri parçasını hemen yeniden yazmadan temsil edilmesini amaçlar; okuma sırasında ek çözümleme maliyeti ve sonraki birleştirme işi oluşabilir. Yeni yaklaşımın tüm sürümlerde aynı olgunlukta olduğu varsayılmamalıdır. Silme ve güncelleme semantiği erişilebilirlik, fiziksel imha ve sıkıştırılmış depolama üzerindeki maliyet bakımından ayrı incelenir.

ClickHouse 25.7 ile SQL tarzı hafif UPDATE, değişen değerleri patch veri parçası olarak saklayan bir yaklaşıma kavuşmuştur. Klasik `ALTER TABLE ... UPDATE` etkilenen veriyi yeniden yazan mutation yoluna dayanırken yeni yol küçük güncellemelerde veri değişikliği kadar kompakt ek verinin yazılmasını hedefler. Patch verileri sorgu okumasına yansıtılır ve daha sonra arka plan birleşmeleriyle fiziksel veri parçasına uygulanabilir. Bu tasarım güncellemeyi mümkün kılar ama yoğun bir OLTP işlem modelinin aynı özellikleriyle eşdeğer hale getirmez.

İki farklı yük sınanmalıdır: 100 milyon satırdan birkaç kaydın değiştirilmesi ve aynı tabloda 90 milyon satırın değiştirilmesi. İlkinde patch yaklaşımı az yazım oluşturabilir; ikincisinde klasik büyük ölçekli mutation daha uygun olabilir. Gerçek sonuca `system.mutations`, `system.parts`, güncelleme gecikmesi, okuma maliyeti ve toplam I/O kullanımı birlikte bakılarak karar verilir. Kaynak: https://clickhouse.com/blog/updates-in-clickhouse-2-sql-style-updates

### 22.3. ReplacingMergeTree Üzerinden Güncelleme ve Fiziksel UPDATE Ayrımı

ReplacingMergeTree'ye yeni sürüm INSERT etmek veri mutasyonu değil çok sürümlü temsil üretmektir. Önceki sürümler birleştirme edilinceye veya FINAL ile okununcaya kadar fiziksel olarak bulunabilir. Sürümleme kaynak işlem sırasını doğru yansıtmıyorsa son değer yanlış seçilebilir.

ReplacingMergeTree yeni durumları INSERT ederek saklayabilir; klasik UPDATE ise mevcut satırın değerini değiştirme semantiği sunar. Sürüm alanlı modelde önceki sürüm fiziksel olarak bir süre daha part'larda kalabilir. `FINAL` ile doğru nihai görünüm elde etmek mümkün olsa da her sorguya bunu eklemek performans maliyeti doğurabilir. Sistem gereksinimi sık noktasal read-after-write ve referans bütünlüğü ise analitik modelin OLTP yerine geçip geçmediği ayrıca sorgulanmalıdır.

Patch-veri parçası yaklaşımında UPDATE sonucu temel büyük veri parçasının tüm sütunlarının hemen yeniden yazılmasını gerektirmez. Değişen değerler ayrı küçük yapıda tutulup sorgu sırasında uygulanabilir ve ilerideki birleştirme ile temel veriye katılabilir. Bu yöntem çok küçük kayıt kümelerinde yüksek hız sağlasa da sürekli ve yoğun değişen alanlar sorgu anında ek birleştirme maliyeti oluşturabilir.

Klasik mutation, lightweight UPDATE ve ReplacingMergeTree farklı doğruluk ve işletim sözleşmelerine sahiptir. İlkinde geniş veri yeniden yazma maliyeti, ikincisinde patch görünürlüğü ve birikimi, üçüncüsünde aynı sıralama anahtarı için çoklu sürümlerin nihai seçimi ölçülür. ClickHouse'un 25.7 sürümünde tanıtılan SQL tarzı UPDATE ve DELETE davranışları, her OLTP işlem garantisinin sağlandığı anlamına gelmez.

### 22.4. Tutarlılık, Anlık Görüntü İzolasyonu ve ACID Sınırları

Atomik veri parçası görünürlüğü, birden fazla tabloyu kapsayan her işlemin tam ACID olduğunu göstermez. İzolasyon ve anlık görüntü garantileri ilgili motor, sorgu ve dağıtım topolojisine göre ayrıştırılır. Yalnızca başarısız komuta bakarak önceki yan etkilerin tamamının geri alındığı varsayılmamalıdır.

Sıralı iki Oracle işlemi düşünelim: T₁ bir hesabı günceller, T₂ bu güncellemeyi referans alarak ikinci tabloya kayıt yazar. Her iki değişiklik CDC topic'lerinden hedefe farklı anlarda gelebilir. ClickHouse sorgusu kısa aralıkta yeni hesap değerini fakat eski ilişki tablosunu görebilir. Bu, kaynak Oracle'ın ACID özelliğinin ihlali değil, analitik kopyanın hedefte tek işlem kesiti olarak sunulmamasıdır. Kaynak SCN/işlem onayı zamanına göre uygulanan bir watermark, kapsamındaki tabloların yeterli ilerleme kaydettiği kesiti belirlemeye yardım edebilir; aynı anda gelmiş olma varsayımının yerini açık doğruluk koşulu alır.

### 22.5. Çok Tablolu ve Dağıtık İşlem Sınırları

Dağıtık bölütler arasında tek işlem onayı noktalı genel işlem gerektiren iş modeli ClickHouse'a doğrudan taşınmamalıdır. Kaynak sistemde tamamlanan çok tablolu işlemler CDC hattında birden çok hedef tabloya gecikmeli yansıyabilir. Karşılaştırmalı raporlama için tutarlı kesit veya watermark gerekir.

Kaynak Oracle'da tek işlem içinde güncellenen iki tablo, CDC hattında ayrı mesajlar veya topic'ler üzerinden aktarılabilir. ClickHouse her tabloya ayrı INSERT ile veri alıyorsa, analitik sorgu kısa bir aralıkta kısmi kaynaşmış durumu görebilir. Bu durum hedefte işlem sınırıyla korunmuş çok tablolu anlık görüntü varmış gibi yorumlanmamalıdır. Kaynak SCN'ye kadar ilerleme kaydı veya tutarlı parti gösterimi, raporlama doğruluğunu tanımlamak için kullanılabilir.

### 22.6. FINAL ve Okunabilirlik Garantileri

`FINAL` engine'in birleştirme semantiğini okuma sırasında uygulayabilir; ancak maliyeti anahtar seçiciliği ve veri hacmine bağlıdır. `FINAL` kullanmak eksik CDC olayını, yanlış sürüm değerini veya hatalı kimlik modelini düzeltmez. Okunabilirlik garantisi ilgili motor kurallarıyla sınırlıdır.

`FINAL`, ReplacingMergeTree gibi motorlarda arka plan birleştirme tamamlanmasa bile sorgu sırasında birleşme semantiğini uygulayabilir. Bu işlem sık sorgulanan geniş veri kümelerinde ek CPU ve bellek kullanabilir. `FINAL` istemeyen sorgular tasarlanırken aynı anahtarın birden fazla sürümüne karşı doğru toplama yapılıp yapılmadığı kanıtlanmalıdır. Motorun fiziksel satır sayısı ile raporun mantıksal olay sayısı her zaman aynı değildir.

### 22.7. Retention, Silinme Anı ile Fiziksel İmha Farkı

Mantıksal silme, sorgunun kaydı döndürmemesi; fiziksel imha, verinin veri parçası veya yedeklerden de çıkarılmasıdır. Replikalar, snapshot'lar ve uzak yedekler ayrı retention yönetimi gerektirir. Yasal silme hedefi yalnız SQL DELETE başarı mesajıyla doğrulanamaz.

Mantıksal silme satırın sorgularda görülmesini engellerken veri parçası dosyası, replika, yedek veya uzak nesne üzerinde fiziksel kopya bir süre daha var olabilir. Retention hedefi “sorgu sonucundan çıkarma” ve “kalıcı ortamların tamamından imha” olarak iki farklı anlam taşır. Veri koruma yükümlülüğü varsa yedek saklama ve replikasyon politikaları da silme planına dahil edilir. TTL çalışma sıklığı ile hukuki imha süresi aynı kabul edilmemelidir.

Mantıksal silme, yeni sorguların kaydı görmemesiyle; fiziksel imha, ilgili verinin saklama katmanında artık bulunmamasıyla ilgilidir. MergeTree part'larında güncelleme/silme sonrasında eski dosyaların kısa bir süre kalması, replikalar, object-store versioning ve yedekler nedeniyle fiziksel yaşam döngüsünü karmaşıklaştırır. Bir saklama süresi politikası uygulandığında canlı tablonun, bağımsız replika ve yedeklerin, veri dışa aktarımlarının ve arama indekslerinin saklama kuralları ayrı tanımlanır.

Silme talebinin tamamlandığına ilişkin güvenilir kayıt, yalnız hedef SQL komutunun başarı kodu değildir. İlgili tablo ve replica üzerinde görünürlük kontrolü, bekleyen mutation olup olmadığı ve arşiv/yedek saklama süresi denetlenmelidir. Silinmiş kaydın replikadan yeniden görünmesi veya eski yedeğin geri yüklenmesi durumundaki düzeltme davranışı kurtarma planının bir parçasıdır.

### 22.8. Hata, Yeniden Deneme, Tekrarlanabilirlik ve Doğrulama Senaryoları

Mutation sırasında sunucu kapanması, partinin tekrar yazılması veya CDC kopması ayrı senaryolardır. İdempotent işlem kimliği, kaynak sequence/SCN ve doğrulama sorguları tasarımın parçasıdır. Yeniden denemeler sonucunda satır veya agregasyon sayıları büyümemelidir.

İstemci `INSERT` isteğinin ardından bağlantı hatası alırsa sunucunun veriyi kalıcı yazıp yazmadığı bilinmeyebilir. Tekrar gönderim için idempotency anahtarının bulunması, aynı olayın iki kez sayılmasını önler. Buna karşılık yanlış anahtar kullanılması farklı olayların yanlışlıkla tekilleştirilmesine yol açabilir. Üretimde hata enjeksiyonu; sunucu yeniden başlatma, ağ kesintisi, Kafka offset gecikmesi, kaynak işlem geri alma'i ve çakışan güncellemeleri içermelidir.

## Ünite 23: Dağıtık ClickHouse, Bölütleme, Replikasyon ve Keeper

Dağıtık sorgu koordinatörü işi shardlara dağıtır; shard içindeki replikalar erişilebilirlik ve çoğaltma sağlar. Sonuçlar üst düğümde yeniden birleştirilir.

![Shard replica dağıtık sorgu animasyonu](https://alikoker.com.tr/svg/distributed-shards-replicas-query.svg "Shard replica ve dağıtık sorgu")


ClickHouse dağıtık mimarisinde bölüt kapasiteyi yatay dağıtır, replica aynı bölüt verisinin yedek okuma kopyasını sağlar. `Distributed` tablo sorguyu fiziksel bölüt tablolarına yönlendirir; ReplicatedMergeTree veri parçası değişimlerini replikalar arasında koordine eder. ClickHouse Keeper üstveri ve koordinasyon için kullanılır; kullanıcı verisinin tümünü Keeper'da tutmak bu mimarinin amacı değildir. Ağ bölünmesi ve replica gecikmesi altında görülen veri kesiti sorgu ayarlarına bağlıdır.

Dağıtık veritabanında bölüt sayısını artırmak yalnız daha fazla CPU sağlamak değildir: her bölüt daha az veri tutarken sorgu başına koordinasyon ve ağ fanout artabilir. Çok küçük bölütler üstveri ve socket sayısını büyütür. Replication ise bölütün veri kümesini birden fazla yerde tutar; replica sayısı yatay veri kapasitesini aynı şekilde artırmaz. `Distributed` motor sorgu sonucunun doğru global aggregation'a ulaşması için kısmi durumları toplayabilir; limit/sort/JOIN gibi işlemlerde semantik dikkat ister. Keeper quorum kaybıyla veri parçası kaybı farklı arıza sınıflarıdır. Yalnız node eklemek hot-key dağılımını düzeltmeyebilir; rebalancing ve bölüt anahtarı ayrıca tasarlanır. Yük devri testinde bir bölütün tamamen erişilememesi ile bir replica'nın devre dışı kalması ayrı denenmelidir.

### 23.1. Bölüt ve Replika Ayrımı ile Küme Topolojisi

İki bölüt ve her bölüt için iki replica, dört fiziksel veri kopyası değil her bölüt verisinin ikişer kopyası anlamına gelir. Bölüt key aynı olayın hangi veri bölümüne gideceğini belirler. Yanlış bölütleme anahtarı hot bölüt ve dengesiz yerleşim yaratabilir.

4 düğümlü dağıtımda iki bölüt, bölüt başına iki replica kullanılabilir. 1 TB mantıksal verinin sıkıştırılmış halinin iki bölüte dengeli dağıldığı kabulünde her bölüt yaklaşık 0,5 TB, her replica 0,5 TB tutar; toplam küme fiziksel veri alanı yaklaşık 2 TB olur. Dağılım dengesizliği, birleştirme sırasında geçici alan, üstveri ve yedekler hesaba katılmamıştır. `Distributed` tablo veri parçaları'ın üçüncü bir tam kopyasını zorunlu kılmaz. Bölüt anahtarı yüksek trafikli tek tenant'ı hep aynı bölüte taşıyorsa denge hesapla beklenen kadar iyi olmayabilir.

### 23.2. ClickHouse Keeper, ZooKeeper ve Üstveri Eşgüdümü

ClickHouse Keeper, replikasyon koordinasyonunda üstveri ve lider seçimi gibi işlemlere hizmet eden ZooKeeper uyumlu bir bileşendir. Keeper'ın tutarlı olması bütün veri part'larının anında replike olduğunu göstermez. Koordinasyon çoğunluğu kaybedildiğinde bazı işlemler durabilirken düğümdeki eski veri okunabilir kalabilir; kesin davranış motor ve ayarlara bağlıdır. Keeper erişilebilirliği ve replica queue durumu ayrı izleme konularıdır.

Üç Keeper düğümünde çoğunluk iki düğümdür. İki Keeper düğümü kaybolursa elde kalan tek düğüm koordinasyon yazıları için gereken quorum'u oluşturamaz; yerel ClickHouse veri parçası dosyalarının otomatik olarak kaybolması beklenmez. Buna karşın yeni replika üstverisinin kabulü, dağıtık DDL ve belirli yazma işlemleri durabilir. Aynı raft üyelerinin tek fiziksel host veya aynı arıza alanında bulunması kağıt üzerindeki üç düğüm çoğunluğunu korumaz.

Keeper log/anlık görüntü durumu, disk gecikmesi, ağ kesilmesi ve saat sapması bağımsız arıza girdileridir. Olay analizi sırasında Keeper'ın lider durumu ile `system.replicas` ve `system.replication_queue` göstergeleri ayrı okunur. Replika gecikmesi olmaması, koordinasyon kümesinin ilerideki ağ bölünmelerini tolere edeceğine ilişkin bir kanıt değildir.

### 23.3. Lider Seçimi, Çoğunluk Kararı ve Replikasyon Gecikmesi

Keeper quorum ile ClickHouse veri okumasının quorum ayarları farklıdır. Belirli replica'dan okuma, son onaylanan verinin bütün kopyalarda görünmesi demek değildir. Yazma onayı, replication lag ve read-after-write gereksinimi tasarım bazında açıklanır.

Keeper quorum, koordinasyon üstverisi için çoğunluk kuralıdır; veri INSERT quorum'u aynı kavram değildir. Replika gecikmesi, bir düğümde onaylanmış değişikliğin diğer düğümün sorgusunda henüz görünmemesine yol açabilir. Read-after-write gereksinimi olan sorgular yalnız rastgele replica yönlendirmesine bırakılamaz. Yazma ve okuma tazeliği gereksinimi kaynak işlem onayı zamanı ve sorgu yönlendirme stratejisiyle birlikte tanımlanmalıdır.

Keeper'ın çoğunluğu, veri kopyasının sorgu için en güncel satırları içerdiği anlamına gelmez. Üç Keeper düğümünde iki düğümün erişilebilir olması koordinasyon kararlarının sürmesini sağlayabilir; ancak tablo replica'larından biri replikasyon kuyruğunda gerideyse bu replica'dan yapılan sorgu eski veri görebilir. Keeper quorum koşulu ile replika yazma onayı veya okuma tazeliği aynı garanti değildir.

Arıza planında ayrı ayrı doğrulanacak üç alan vardır: koordinasyon çoğunluğu, gerekli bölütün en az bir sağlıklı replica'sı ve istemcinin yönlendirildiği düğümün beklenen veri durumuna erişimi. Replikasyon kuyruğunu gösteren sistem tabloları ve istemcinin tutarlılık hedefi birlikte değerlendirilir. Ağ bölünmesinde istemci tarafının otomatik yeniden denemesi işlemi iki kez çalıştırabileceğinden INSERT deduplikasyonu ve sorgu tekrarlama semantiği bağımsız ele alınır.

### 23.4. ReplicatedMergeTree ile Veri Parçalarının Çoğaltılması

ReplicatedMergeTree veri parçası üstverisini koordine ederek uyumlu veri parçası kopyalarını replikalara taşır. Replica gecikmesi sorgu sonuçlarında veri tazeliği farkı yaratabilir. Replika kontrolü `system.replicas`, `system.replication_queue` gibi tablolar üzerinden yapılır.

Replica ve dağıtım durumu, sistem tablolarından izlenir:

```sql
SELECT
    database,
    table,
    replica_name,
    is_readonly,
    absolute_delay,
    queue_size
FROM system.replicas
ORDER BY absolute_delay DESC;
```

Bu tablo replikalı olmayan MergeTree tabloları için genel kayıt listesi değildir.

ReplicatedMergeTree, veri parçası aktarımı ve replikalar arası üstveri koordinasyonu yoluyla aynı bölüt içindeki veri kopyalarını korur. Replikasyon, her an tüm replikaların aynı anda aynı sonucu döndürdüğü anlamına gelmez. Geçici lag, ağ kopması, asenkron insert ve arka plan replikasyon kuyrukları sonucunda farklı sorgu anlarında farklı görünürlük oluşabilir. Uygulama belirli bir write-after-read garantisi gerektiriyorsa okuma rotası, quorum ayarları ve ilgili veri sürümü ayrıca ele alınır.

Bölüt ile replica farklı sorumluluklara sahiptir: bölüt veri kümesinin bir bölümünü tutar, replica aynı bölütün yüksek erişilebilirlik kopyasını sağlar. Üç bölüt ve iki replica yapısı mantıksal veriyi üçe böler ve altı sunucu kopyası oluşturabilir; her sunucunun tüm veriyi taşıdığı varsayımı yanlıştır. Keeper üstveri ve koordinasyon için gerekir, kullanıcı olaylarının tümünü depolayan analitik sunucu değildir. Replikasyon gecikmesinin ölçümünde `system.replicas` ve `system.replication_queue` yalnız anlık göstergeler sağlar; yeniden başlatma, büyük veri parçası indirme ve disk doygunluğu ile birlikte yorumlanır.

ReplicatedMergeTree veri part'larının kopyalanmasını ve replikaların koordinasyonunu destekler. Replikasyonun varlığı, yazmanın bütün replica'larda aynı anda görünmesi veya tek makinedeki kayıp dışında bütün arızalara dayanıklılık demek değildir. Replica geride kaldığında okuma yönlendirme ve yazma onayı ayarları beklenen tazelik koşulunu etkiler. Bir replication queue birikimini yalnız replikasyon hızı değil ağ, object store, Keeper erişimi ve yerel birleştirme yükü de etkileyebilir.

### 23.5. Distributed Motoru ve Dağıtık Sorgu Dağıtımı

Distributed motor çok düğümlü SELECT'i yönlendirip kısmi sonuçları birleştirebilir. INSERT dağıtım kuyruğu ve yeniden deneme ayarları teslim semantiğine etki eder. Fiziksel veri yerel bölüt tablolarındadır; yalnız Distributed tablo oluşturmak otomatik replica sağlamaz.

`Distributed` tablo sorguyu altında tanımlı bölütlere yönlendirebilir; bu tablo motoru veriyi otomatik olarak tek mantıksal işlem altında birleştirme garantisi vermez. Sorgu planında bölüt başına okuma ve yerel agregasyon yapılırken coordinator düğümünde final sonuç hesaplanabilir. Hatalı bölütleme key aşırı büyük bir bölüt, skew ve dengesiz CPU kullanımına yol açar. Sorgu zamanını azaltmak için bölüt sayısını artırmadan önce ağda taşınan ara verinin hacmi ölçülmelidir.

### 23.6. Bölütler Arası Toplulaştırma, JOIN ve Dağıtık DDL

Dağıtık GROUP BY yerel kısmi sonuçlardan global birleşmeye gider. Bölütler arası JOIN çok büyük sağ tablo aktarımı yaratabilir; GLOBAL türleri farklı fanout semantiğine sahiptir. Distributed DDL her düğümde tamamlanmadan şema eşitliği varsayılamaz.

Dağıtık agregasyonda her bölüt `sumState` benzeri kısmi durumlar üretebilir; coordinator bu durumları birleştirerek doğru sonucu oluşturur. Kesin benzersiz sayımda farklı shard'larda aynı kimliğin bulunabilmesi gerekir; yerel distinct sayılarını toplamak yanlıştır. Dağıtık DDL işlemlerinin gönderilmiş olması da bütün düğümlerde tamamlandığı anlamına gelmez. Şema sürümü uyuşmazlığının sorguya yansımaması için rollout ve doğrulama aşamaları tanımlanmalıdır.

Dağıtık toplamada her bölüt `GROUP BY` ara durumları üretip koordine eden düğüme gönderdiğinde ağ maliyeti ham satır sayısından çok grup kardinalitesine bağlı hale gelir. H grup ve durum başına s bayt için ara aktarım yaklaşık H × s büyüklüğündedir; `uniqExactState` gibi değişken boyutlu durumlarda s sabit değildir. Birleştirilmiş sonuçların `FINALIZE` öncesindeki biçimi ve bölüt arızasında kısmi sonuç politikası tanımlanmalıdır. Yüksek kardinaliteli anahtarlarla bölüt sayısını artırmak, bütün ağ maliyetini doğrusal azaltmaz.

### 23.7. Arıza Türleri, Kısmi Sonuçlar ve Kurtarma

Bir bölüt erişilemezse hata dönmekle eksik sonucu kabul etmek farklı iş kararıdır. `skip_unavailable_shards` gibi ayarlar sonuç bütünlüğünü etkileyebilir. Hata sonrası queue replay, kayıp veri parçası, bozuk disk ve replikasyon yeniden eşleştirme senaryoları ayrılır.

Bir bölüte erişilemeyen sorgunun kısmi sonuç üretmesine izin veriliyorsa sonuç, eksik veriyi açıkça belirtmeden nihai rapor olarak kullanılamaz. Bir replica'nın yeniden başlatılması sırasında Keeper bağlantısı, bekleyen fetch görevleri ve yerel veri parçası üstverisi tutarlı duruma getirilir. Yük devri sonrasında aynı sorgunun sonuç sayısı değişiyorsa replication lag ve ilgili sorgunun tutarlılık sözleşmesi incelenir. Dağıtık sistemde erişilebilirlik ile tam sonuç garantisi arasında açık tercih yapılır.

Üç düğümlü Keeper kümesinde çoğunluk iki düğümdür. Tek düğüm kaybı çoğunluk korunuyorsa koordinasyonun sürmesine izin verebilir; iki düğüm kaybında yeni koordinasyon kararları alınamaz. Bu durum her replica'nın yerel olarak zaten yazılmış veri parçalarını anında okunamaz hale getireceği anlamına gelmez. Fakat replika üstverisi veya dağıtık DDL gerektiren işlemler bloke olabilir. Beklenen davranış sunucu sürümü, erişilen tablo motoru ve hatanın evresine bağlıdır.

Veri kurtarma senaryosunda önce hata anındaki canlı replica'ların en son veri parçası/checksum durumları karşılaştırılır; ardından Keeper koordinasyonunun tekrar sağlanması ve kayıp veri parçalarının yeniden alınması değerlendirilir. Rastgele replica dizinlerinin kopyalanması veya koordinasyon üstverisinin geriye döndürülmesi, veri kaybı doğurabileceğinden geri yükleme adımı olarak kabul edilmez. Replica sayısı, arıza alanlarının bağımsızlığını sağlamıyorsa yüksek erişilebilirlik iddiası geçersizdir.

### 23.8. Yatay Ölçekleme, Yeniden Dağıtım ve Küme Tutarlılığı

Yatay genişleme yeni bölüt açıldığında eski verinin otomatik ve eşit dağıtıldığı anlamına gelmez. Rebalancing yeni ve eski verinin taşınmasını gerektirebilir. Cluster topology değişiklikleri istatistiklerin zaman serisi karşılaştırmasını ve kapasite ölçümünü etkiler.

Bölüt sayısını artırmak geçmiş veri parçalarını otomatik olarak dengeli dağıtmayabilir; veri yeniden dağıtımı ek ağ, disk ve CPU yükü doğurur. Yeni bölüt anahtarına geçiş, eski ve yeni verinin farklı fonksiyonlarla dağıtıldığı geçiş dönemini gerektirebilir. Bu süreçte iki kez görünen veya görünmeyen olayların oluşmaması için yeniden taşıma sınırı, kaynak kimlikleri ve doğrulama toplamları kullanılmalıdır. Replica sayısını artırma ise veri kapasitesini değil okuma kapasitesini veya kullanılabilirliği hedefleyebilir.

## Ünite 24: Harici Depolama ve Katmanlı Veri Mimarileri

Depolama politikası ClickHouse verisini tek bir diskten çok katmanlı ortama taşıyabilir. Yerel NVMe düşük gecikme sunarken nesne depolama kapasite ve dayanıklılık açısından avantaj sağlayabilir; ancak egress, API istek maliyeti ve önbellek doğruluğu hesabın parçasıdır. Veri parçası üstverisi ile data block'larının farklı katmanlarda olması kurtarma ve okunabilirlik açısından ayrıca incelenir.

Katmanlı depolamada en düşük GB başına bedel her zaman en düşük toplam maliyeti sağlamaz. Harici object store üzerinde sık tekrar eden düşük seçicilikli sorgular önbellek hit oranı düşükse çok sayıda ağ isteği üretir. Disk politikası sıcak veri için NVMe kullanırken geçmişi uzak bir katmana taşıyabilir; TTL MOVE yalnız yerleştirmeyi değiştirir, veri sorgusunun doğruluğunu doğrudan değiştirmez. Veri her katmanda şifreleme, erişim denetimi ve yedekleme yükümlülüğünü taşır. Objekt store'da gecikmiş/başarısız istekler için yeniden deneme politikası üretimde izlenmelidir. Anlık görüntü restorasyonu ile yalnız üstveri restorasyonu arasındaki fark, kalıcı veri parçalarının gerçekten nerede bulunduğuyla açıklanır.

### 24.1. Disk, Depolama Politikası ve Birim Kavramları

Disk fiziksel ya da mantıksal veri hedefini, volume disk grubunu, depolama politikası ise veri parçaları'ın yerleşim kurallarını tanımlar. Veri parçası hareketi bağımsız bir bakım işidir; sorgu sırasında beklenmedik disk geçişi yaşanabilir. Her diskin doluluk ve I/O sınırı ayrı izlenir.

Bir disk tanımı yerel dosya sistemi, nesne deposu veya özel bir saklama katmanını temsil edebilir; volume birden fazla diskten oluşan yerleşim grubudur. Depolama politikası bu volume'ların hangi amaçla kullanılacağını ve yer değiştirme davranışını düzenler. Fiziksel yerleşim, tablo motoru ve TTL kuralı arasındaki ilişki yanlış kurulursa verinin beklenmedik biçimde uzak katmana taşınması sorgu gecikmesini artırabilir.

### 24.2. Yerel Disk, S3, Azure Blob ve Uzak Nesne Depolama

S3 ve Azure Blob gibi object store'larda dosya sistemi gibi rastgele küçük okuma varsayımı uygun değildir. İstek sayısı, ağ RTT, request yeniden deneme ve byte aktarımı performansı etkiler. Yapılandırmada kimlik bilgileri doğrudan SQL metnine gömülmemelidir.

Nesne depolama sistemleri yerel POSIX dosya sistemiyle aynı gecikme profiline sahip değildir. Nesne GET istekleri, ağ RTT'si, object-store işlem hacmi, yeniden deneme maliyeti ve önbellek hit oranı sorgu süresini etkiler. MergeTree'de küçük veri parçası ve küçük blokların çok sayıda uzak isteğe neden olabildiği durumlarda bant genişliği yüksek olsa bile uzak isteklerin sabit gecikmesi sınırlayıcı olabilir. Üstveri nesnelerinin güvenilir yönetimi, yerel önbellek kapasitesi ve arka plan birleştirme stratejisi depolama politikasının parçasıdır.

S3/Azure benzeri katmanlarda saklama bedeli ile okuma/egress ve API çağrısı bedelleri ayrıdır. “Daha ucuz GB” kararı, aynı veri üzerinde yoğun random read iş yükü bulunduğunda daha yüksek toplam maliyet doğurabilir. `T_uzak ≈ N_istek×RTT_etkin + B_transfer/β_etkin` modeli eşzamanlı bağlantılar ve önbellek bulunmadığında ilk yaklaşımdır; gerçek sistemde istekler örtüşebildiği için bu ifade tek sorgunun kesin süresini vermez. Hot/soğuk katman seçimi veri yaşı kadar erişim sıklığı ve sorgu önemiyle de ilgilidir.

### 24.3. Paylaşılan Diskli ve Paylaşımsız Depolama Yaklaşımları

Paylaşımsız bölüte ait yerel veriyle çalışır; ayrık storage/compute yaklaşımlarında ortak nesne depolama ve önbellek koordinasyonu bulunabilir. Sistem aynı ClickHouse SQL arayüzüne sahip olsa da hata ve yeniden başlatma maliyetleri farklılaşır.

Paylaşımsız mimaride düğümler verinin kendi bölümlerini ve işlem gücünü kullanır; paylaşılan diskli düzeninde düğümler ortak depolama katmanına erişebilir. Nesne deposuna erişimin ağ üzerinden gerçekleşmesi, bütün üstveri ve önbellek davranışının kendiliğinden tutarlı olacağını göstermez. Fiziksel veri parçası sahipliği, onaylanan üstverinin görünmesi ve önbellek geçersizleştirme semantiği ayrı mekanizmalardır. Bir mimarinin yalnız depolama ismine bakılarak sınıflandırılması yetersizdir.

Paylaşılan nesne depolama ile paylaşılan dosya sistemi aynı semantik değildir. Nesne deposu üzerinde değişmez veri parçası nesneleri ve atomik üstveri geçişleri kullanılması, herhangi bir düğümün aynı fiziksel dosyaya eşzamanlı rastgele yazabileceği anlamına gelmez. Compute/storage ayrıştırmasının yararı, sorgu ve veri tutma kaynaklarının bağımsız ölçeklenebilmesidir; bedeli ağ aktarımları, önbellek ısınması ve üstveri koordinasyonudur.

Maliyet hesabında toplam depolama ücretine ek olarak nesne istek ücretleri, dışarı veri aktarımı, önbellek diski ve kurtarma sırasında tekrar indirilen veriler bulunur. Çalışma kümesi önbelleğe sığıyorsa uzak depolama gecikmesi gizlenebilir; rastgele eski zaman aralıklarında dolaşan sorgular önbellek hit oranını düşürür. Böyle iş yüklerinde tek bir sıcak başarım karşılaştırması mimari karşılaştırması için yeterli değildir.

### 24.4. Katmanlı Sıcak–Ilık–Soğuk Depolama ve TTL MOVE

Sıcak verinin hızlı diskte, eski dönemlerin daha düşük maliyetli katmanda tutulması retention sorunu ile birlikte tasarlanır. TTL MOVE kayıtları zaman koşuluna göre taşıyabilir; bütün sorguların son dönem aralığına odaklandığı varsayılmamalıdır. Geri tarama sıklığı gerçek trafikle ölçülür.

TTL MOVE verinin yaşına göre hızlı diskten daha ucuz saklama katmanına taşınmasını sağlayabilir; ancak uzak disk üzerindeki veri parçasının okunması her zaman cache-hit kadar hızlı olmaz. Erişim sıklığı yüksek, yaşı eski veri sıcak kalabilir. Bu nedenle sıcak-soğuk ayrımı yalnız yaşa değil sorgu dağılımına bağlı olmalıdır. Taşıma sırasında oluşan ağ ve üstveri işlemleri de toplam depolama maliyetine dahildir.

### 24.5. Önbellek, Üstveri ve Nesne Depolama Tutarlılığı

Object-store üstveri ve yerel önbellek eşleştirmesi, veri parçasının doğru sürümünün okunduğunu güvenceye almalıdır. Önbellek silinmesi verinin kalıcı olarak kaybolması demek değildir; kaynak object store ulaşılabilir olmalıdır. Önbellek hit oranı yalnız performans ölçüsüdür.

Önbellek, uzak depolamanın bütün ağ maliyetini ortadan kaldırmaz. Dataset sıcaklığını, önbellek kapasitesini, indeks blokları ile veri bloklarının önceliklerini ve aynı sunucudaki kullanıcıların erişim örüntülerini birlikte düşünmek gerekir. Örneğin 2 TB aktif sorgu çalışma kümesine karşılık 256 GB önbellek bulunması, erişimlerin büyük bölümünün benzer 100 GB'lik alt kümede yoğunlaşması durumunda yeterli olabilir; erişimler bütün dataset üzerine eşit dağılıyorsa yüksek miss oranı üretir.

Sorgu benchmark'ında remote object storage ile local SSD karşılaştırılırken önbellek temizliği ve yeniden denemeler raporlanmalıdır. Ağ bölünmesi, kısa süreli erişim hataları ve yeniden başlatma sonrası üstveri erişimi tutarlılık senaryolarında ele alınır. Bir replica'nın uzak nesneye erişebilmesi diğer bütün replica'ların aynı anda aynı performansla okuyabileceği anlamına gelmez.

26.10'da `s3_plain_rewritable` diskler için hard-link tabanlı nesne referanslama seçeneği duyurulmuştur. Mutasyon sırasında değişmeyen dosyaları yeniden kopyalamadan yeni veri parçası düzeninin kurulabilmesi, nesne depolama üzerinde ağ trafiğini azaltabilir; ancak üstveri doğruluğu ve eski sunucularla geriye dönük uyumluluk riski taşır. `enable_hard_links` varsayılan olarak kapalıdır. Aynı sunumda yaklaşık 500 bin nesne ve 36 bin dizin içeren örnekte üstveri yükleme süresinin 116 saniyeden 37 saniyeye düştüğü raporlanmıştır. Bu oran, nesne sayısı, prefix dağılımı ve uzak depolamanın listeleme davranışına bağlıdır. [41]

### 24.6. Okuma/Yazma Verimi, Ağ Aktarımı ve Maliyet

Toplam depolama maliyeti: kapasite × birim fiyat + okuma/yazma istekleri + ağ transferi + compute + replikalar + backup. Sık küçük okuma object-store istek bedelini artırabilir. Donanım kıyasında aynı durability ve kurtarma hedefleri kullanılır.

Nesne deposu maliyeti yalnız saklanan TiB üzerinden hesaplanmaz. Okunan byte, GET/LIST çağrıları, ağ aktarımı, bölgeler arası egress ve önbellek doldurma sıklığı toplam TCO'yu belirler. Çok sayıda küçük veri parçası için üstveri ve istek maliyeti büyük veri parçasından farklıdır. Sık yapılan tam tarama uzak nesne deposundan tekrar tekrar veri çekiyorsa ilk bakışta ucuz depolama pahalı çalışma zamanına dönüşebilir. Bu nedenle maliyet modeli sorgu dağılımını da içerir.

Apache Iceberg v3 deletion vectors, silinen satır konumlarının bitmap temsilleri üzerinden okuma sırasında elenmesini sağlar. ClickHouse 26.10'un bu gösterimi okuyabilmesi, verinin fiziksel Parquet dosyasından hemen silindiği anlamına gelmez. Bir veri gölünde silme görünürlüğü, üstveri anlık görüntüyü, deletion-vector referansı ve veri dosyası sürümü birlikte değerlendirilir. Iceberg v2 konumsal silme dosyalarından v3 silme vektörlerine geçişte testin aynı veri snapshot'ına dayanması gerekir. Yanlış önbellek geçerliliği veya eksik üstveri senkronizasyonu, kaldırılmış satırların geçici olarak görünmesine yol açabilir. Yeni okuyucu davranışları dağıtık kümede farklı sürüm kullanan düğümler üzerinde ayrıca sınanmalıdır. [41]

### 24.7. ClickHouse-disks ve Depolama İncelemesi

`clickhouse-disks` dosya ve disk politikalarının incelenmesinde kullanılabilir; yönetim komutlarının etkileri hedef dağıtımda doğrulanır. Disk alanını yalnız `df` üzerinden okumak object-store hacimlerini ve veri parçası üstverisini kapsamayabilir. `system.disks` ve `system.storage_policies` birlikte değerlendirilir.

Depolama politikası ve disk görünümü:

```sql
SELECT name, path, type, free_space, total_space
FROM system.disks
ORDER BY name;
```

Uzak depolama için bildirilen kapasite ve boş alan davranışı yerel dosya sistemindeki değerlerle birebir aynı olmayabilir.

`clickhouse-disks` ve sistem tabloları saklama politikasındaki yerleşimin ve veri parçalarının izlenmesinde kullanılabilir. Bir veri parçasının depolama katmanında hangi diskte bulunduğu yönetim kararı için önemlidir; dosya sistemi seviyesinde manuel değişiklik yapılması üstveri tutarsızlığı doğurabilir. Depolama kapasitesi hesaplanırken etkin veri parçaları, geçici birleşme alanı, replikalar ve yedek saklama ayrı toplanmalıdır.

## Ünite 25: İstemciler, Sürücüler, API ve Ağ Protokolleri

ClickHouse aynı sorgu motoruna ulaşan birden fazla erişim protokolü ve sürücü sunar. İstemci seçiminde yalnız bağlantı desteği değil, büyük sonuç akışını parça parça okuma, iptal mekanizması, yeniden deneme, sıkıştırma, tip eşleştirme ve güvenlik gereksinimleri göz önüne alınır. SQL sonuçlarının HTTP üzerinde aktarımı ile yerel binary protokol üzerinde aktarımı aynı ağ yükü ve serileştirme maliyetini oluşturmaz.

Bir sorgunun istemciden ölçülen toplam gecikmesi ağ kurulumu, kimlik doğrulama, sorgu çözümleme, çalışma, sonuç serileştirme ve aktarımdan oluşur. İki sürücü aynı sunucu sorgu süresine sahip olsa da farklı blok fetch size ve sıkıştırma desteği nedeniyle uygulamada farklı hız gösterebilir. Zaman serisi değerleri Java/JDBC üzerinden yerel saat dilimine yanlış dönüştürülürse performans açısından başarılı görünen aktarım analitik sonucu bozar. HTTP akış işleme büyük çıktı kümesinin tamamının istemci belleğinde tutulmasını önlemeye yardım edebilir. Yeniden deneme sırasında zaman aşımının sunucuda INSERT'in tamamlanmadığını kanıtlamadığı unutulmamalıdır. Bu nedenle sorgu id'si, idempotency ve client timeout sözleşmeleri birlikte tasarlanır.

### 25.1. Yerel TCP, HTTP/HTTPS ve gRPC

Native TCP ikili sorgu ve veri transferini, HTTP/HTTPS kolay entegrasyonu sağlar; gRPC farklı sözleşmeye sahip erişim seçeneği olabilir. Sürüme bağlı port ve varsayılan auth ayarları doğrulanır. HTTP ile büyük sonuçlarda akış işleme, keep-alive ve response compression önemlidir.

Native TCP protokolü ClickHouse'un tür bilgisi ve ikili veri iletimi için optimize edilmiş istemci bağlantısıdır; HTTP/HTTPS, SQL göndermeyi ve farklı satır/kolon formatlarında sonuç almayı kolaylaştırır. İstemci sürücüsünün desteklediği sıkıştırma, blok boyutu, hata akışı ve sorgu id davranışı uçtan uca performansı etkileyebilir. HTTP keep-alive ve bağlantı yeniden kullanımı, her sorguda TCP/TLS el sıkışması maliyeti ödenmesini engelleyebilir. Ancak bir yük dengeleme katmanında zaman aşımı, maksimum bağlantı ve sunucu başına concurrency sınırları uyumlu seçilmelidir.

Büyük sonuç kümelerinin API tarafından gereksiz JSON nesnelerine çevrilmesi bellek tahsisini ve GC baskısını artırabilir. sütun yönelimli Arrow/Parquet benzeri biçimler veri bilimi iş yüklerinde etkili olabilir; bunların uygunluğu istemci tüketim modeline bağlıdır. Bir milyar satırlık analitik sorgunun yalnız yüz satırlık özet döndürmesi bekleniyorsa sonucu sunucu tarafında gruplayarak istemciye taşımak ağ maliyetini azaltır. Çok büyük ham export ihtiyacında ise stream tüketimi ve backpressure önem kazanır.

### 25.2. ClickHouse İstemcisi, SQL Konsolu ve Web Arayüzü

`clickhouse-client`, sunucunun native protokolü üzerinden etkileşimli ve toplu SQL yürütmek için kullanılır; HTTP tabanlı sürücüler ve web arayüzleri farklı oturum, çıktı ve bağlantı davranışlarına sahip olabilir. Aynı sorgunun CLI'da hızlı, tarayıcıda yavaş görünmesi doğrudan sunucu planlayıcısından kaynaklanmayabilir: sonuçların JSON biçimine dönüştürülmesi, ağ üzerinden aktarılması ve tarayıcıda tabloya çizilmesi ayrı maliyetlerdir.

Ölçümlerin karşılaştırılabilir olması için sürüm, kullanıcı profili, etkin SETTINGS, zaman aşımı, çıktı biçimi ve sonuç satırı sınırı sabitlenir. `LIMIT 100` uygulanmış bir sorguyla bütün satırları gönderen sorgunun duvar saati karşılaştırılamaz. CLI veya API'nin isteği zaman aşımına uğrattığı durumda sorgunun sunucuda sürmesi de mümkündür; sorgu kimliği ve sunucu tarafı tamamlanma kaydı kontrol edilmelidir.

Sorgu davranışının güvenilir referansı istemcide gösterilen süre değil, sunucunun yürütme ölçümleridir. `system.query_log` üzerinden `query_id`, `read_rows`, `read_bytes`, `query_duration_ms`, `memory_usage` ve hata durumu birlikte incelenir; log yazımı yapılandırmaya ve günlük boşaltma zamanına bağlı olabilir.

ClickHouse arayüz dokümantasyonunda SQL Console yanında sonuç şekillendirme, sütun sabitleme, renklendirme ve notebook işlevleri de yer alır. Bunlar sunucunun saklama ve sorgu optimizasyon garantilerini değiştiren DBMS özellikleri değil, kullanıcı arayüzü katmanındaki sunum işlemleridir. Bir notebook hücresi aynı SQL'i yeniden çalıştırabilir; sonucun belleğe alınması, gösterim için örneklenmesi ve sayfalara bölünmesi sorgu sonucu ile görselleştirilen veri arasındaki farkı etkiler. UI ekranındaki satır sayısı, sorgunun işlediği toplam kayıt sayısı değildir. Üretim incelemesinde UI'nin örnekleme/satır sınırları kaydedilmelidir. [7]

### 25.3. MySQL ve PostgreSQL Protokol Uyumluluğu

MySQL ve PostgreSQL wire-protocol compatibility bazı araçların kolay bağlanmasını sağlar; hedef motorun PostgreSQL veya MySQL'in işlem ve fonksiyon semantiğini üstlendiği anlamına gelmez. ORM davranışı ve sürücü özellikleri ayrı test edilmelidir.

ClickHouse'un MySQL/PostgreSQL protokol uyumluluğu sunan arabirimleri, bu veritabanlarının bütün SQL ve işlem özelliklerini uyguladığı anlamına gelmez. Hazır BI istemcileri sürücü değiştirmeden bağlanabilir; buna rağmen tip dönüşümü, NULL semantiği ve sorgu sözdizimi sınanmalıdır. Protokol kabulü ile kaynak ürünün davranışsal uyumluluğu farklı test başlıklarıdır.

Protokol aracılığıyla bağlanan istemci, `BEGIN`, cursor veya server-side prepared statement gibi özelliklerin tümünü kaynak ürünle aynı davranışta bekleyebilir. Uyumluluk sınaması için bağlantı kurmayı değil, kullanılan gerçek BI sorgularını, veri türü dönüşümlerini ve hata durumlarını temel almak gerekir. Veri aktarımında protokol ismi ile ClickHouse SQL dialect'i ayrı sözleşmelerdir.

### 25.4. JDBC, ODBC, ADBC, Arrow Flight ve Yerel Arayüzler

JDBC/ODBC BI araçlarına bağlantı, ADBC/Arrow ise sütun yönelimli veri aktarımının bazı kullanım biçimlerini destekler. Arrow Flight erişimi kullanılan dağıtımda doğrulanır. Veri tipi ve timestamp dönüşü doğru değilse aktarım hızlı olsa bile analitik yanlış olabilir.

JDBC ve ODBC veri erişimine standart arabirim sunar; ADBC ise kolonlu analitik veri aktarımını ve Arrow ekosistemiyle daha az kopyalama ihtiyacını hedefler. Aynı SQL sorgusu farklı sürücülerde farklı serileştirme, şema çıkarımı ve numeric dönüşüm maliyetlerine sahip olabilir. `UInt64` gibi büyük unsigned sayılar, `DateTime64` hassasiyeti, Decimal ölçeği ve NULL değerleri tüm istemci dillerinde aynı ilkel türlerle temsil edilemez; dönüşümler sessiz yuvarlama veya overflow yaratmamalıdır.

Java servisinde JDBC sonuçlarının satır satır nesnelere map edilmesi, sunucunun hızlı hesapladığı sorgu üzerinde uygulama tarafında yeni bir bellek sınırı oluşturabilir. İstemci seçimi yalnız sürücü kurulabilirliği üzerinden değil p99 uçtan uca gecikme, aktarılmış bayt, ayrıştırma CPU ve heap tahsisi üzerinden yapılır. REST API uçlarında kullanıcı isteğine doğrudan keyfi SQL iletmek yerine sorgu yetkisi ve kaynak sınırları sunucu tarafında uygulanmalıdır.

### 25.5. Çerçeveleme Biçimleri ve Büyük Veri Aktarımı

Framing, bir akışta kayıt sınırının nerede başladığını belirler. Newline-delimited JSON ile tek JSON dizisinin parsing ve error kurtarma koşulları farklıdır. Parquet/Arrow parti aktarımında şema ve sütun yerleşimi serileştirme giderini azaltabilir.

HTTP veri aktarımında isteğin gövdesi ile sunucu yanıtının ayrıştırılması maliyet oluşturur; büyük sonuçlar için akışlı aktarım bellek kullanımını sınırlayabilir. Native protokol tip ve sıkıştırma açısından farklı performans sağlayabilir. Sonucun sunucuda tamamlanması ile istemcide bütünüyle tüketilmesi farklı gecikmelerdir. Büyük veri alımında network timeout, kısmi aktarım ve tekrar gönderimin veri tekilliğine etkisi yönetilmelidir.

Büyük sonuçlarda ağ üzerinden taşınan sıkıştırılmış blokların çözülmesi ve istemci nesnelerine dönüştürülmesi toplam yanıt süresinin önemli bir bölümünü oluşturabilir. Sunucunun sorguyu 200 ms'de tamamlayıp 2 GB sonucu istemciye 3 saniyede aktarması, “200 ms uçtan uca gecikme” olarak raporlanamaz. Sorgu işleme, ilk bayt zamanı ve tam sonuç tüketme süreleri ayrı raporlanmalıdır.

Biçim seçiminde CSV, JSONEachRow, Native ve Parquet'in farkı yalnız dosya boyutu değildir. Native biçim tür bilgisi ve blok aktarımıyla ClickHouse istemcileri için uygundur; Parquet sütunlu parti işleme ve sistemler arası dosya değişimi için yararlı olabilir; satır temelli JSONEachRow hata teşhisi ve farklı hizmetlerle entegrasyon kolaylığı sağlar. NULL, Decimal ve zaman dilimi dönüşümlerinin iki tarafta aynı sonucu üretmesi entegrasyon testinin parçasıdır.

### 25.6. Şema Çıkarımı ve API Yanıt Biçimleri

HTTP sonucu `FORMAT JSON`, `JSONEachRow`, `CSV`, `Native` gibi biçimler olarak üretilebilir. Aynı sorgunun geri döndürdüğü üstveri ve sayısal precision çıktı formatına göre değişebilir. Otomatik tip çıkarımı ilk veri örneklerinin sınırlarına bağlıdır.

JSON sonuç biçiminde büyük `UInt64` değerinin JavaScript number'a otomatik dönüştürülmesi tam sayı hassasiyetini kaybettirebilir. Tarih ve ondalık sayılar da istemci sürücüsüne göre farklı türlere eşlenebilir. API düzeyindeki yanıt şemasının kesinliği, sorgu sonucunun doğruluğu kadar önemlidir. Kullanıcıya sunulan agregasyon sonuçları `Nullable` ve sayısal birim bakımından sözleşmeyle tanımlanmalıdır.

Bir API sonucunda sunucu doğru `UInt64` üretmiş olsa bile istemcinin 53 bit mantissa sınırındaki JavaScript sayı türüne dönüştürmesi veri kaybı doğurabilir. Büyük kimlikler ve sayaçlar için string kodlama veya tam sayı destekleyen istemci türleri kullanılabilir. Bu ayrım sorgu algoritması değil veri serileştirme doğruluğu meselesidir.

26.8 sürümündeki özelleştirilebilir HTTP işlemleyicileri ve akış yanıtları, ClickHouse sorgularını belirli URL uçları aracılığıyla sunmaya imkan verir. Bu yaklaşım, bağımsız uygulama sunucusu olmadan sınırlı analitik servisler oluşturabilse de URL'nin biliniyor olması bir yetki sınırı değildir. İşlemleyici çağrısının yetkileri doğrulanmış kullanıcıdan gelir; her uç için ayrıca kural tanımlandığı varsayılmamalıdır. Sonuç akışı sırasında bağlantı kesilmesi ile sorgunun sunucuda tamamlanması farklı olaylardır. Özellikle dışa veri aktaran sorgularda hız sınırı, satır sınırı, çıktı biçimi, kullanıcı kotası ve iz kaydı birlikte yapılandırılmalıdır. [46]

### 25.7. TLS, SSH, Uç Nokta Mimarisi ve Bağlantı Havuzlama

TLS, istemci kimlik doğrulaması, SSH tüneli ve connection pooling farklı katmanları korur. Ağ oturumunun yeniden kullanımı gecikmeyi düşürebilir; fakat sınırsız bağlantı sayısı server thread ve socket bütçesini tüketir. Yeniden deneme yalnız idempotent ve sonucu bilinmeyen isteğin sözleşmesiyle güvenlidir.

TLS bağlantısı uçlar arasında şifreleme sağlar; sunucu sertifikasının host adı ve güven zinciri denetlenmedikçe aktif araya girme riskinin tamamı giderilmez. SSH bağlantısı yönetim veya tünelleme için kullanılabilir, fakat veritabanı kullanıcı yetkisinin yerini almaz. Connection pooling, oturum kurma maliyetini azaltabilir; uzun yaşayan bağlantılarda stale socket ve server restart davranışı ele alınmalıdır. Her bağlantı için ayrı kaynak sınırı ile kullanıcı bazlı toplam kota farklı politikalardır.

### 25.8. Prometheus, MCP ve Diğer Entegrasyon Protokolleri

Prometheus exposition formatı metrik aktarımı sağlar; MCP veya üçüncü taraf araç protokolleri farklı kullanım yüzeyleridir. Bunların etkinleştirilmesi yeni ağ giriş noktası ve yetkilendirme sorumluluğu oluşturur. Bir protokolün bulunması üretimde zorunlu açılması gerektiği anlamına gelmez.

Prometheus biçiminde metrik sunumu, veritabanının sorgu işlemeye ilişkin iç sayaçlarının dış izleme sistemince alınmasını sağlayabilir. MCP veya benzeri entegrasyon katmanları ayrı yetki ve ağ erişimi sınırları gerektirir. Analitik SQL'e otomatik erişim veren her aracın sorgu kotası, veri maskeleme ve kimlik doğrulama koşulları sunucu tarafından uygulanmalıdır; entegrasyon teknolojisinin varlığı erişim yetkisi oluşturmaz.

ClickHouse 26.9, TimeSeries motoru ve PromQL erişimini ClickHouse Cloud tarafında özel önizleme kapsamında genişletmiştir; bütün self-hosted kurulumlarda varsayılan olarak üretim kullanımına açık oldukları varsayılmamalıdır. Prometheus uyumlu sorgu arayüzü, SQL protokolü veya native istemcinin yerini koşulsuz biçimde almaz. Metrik sorgusunun PromQL semantiği, özellikle etiket eşleşmesi, zamansal örnekleme, `NaN` davranışı ve eksik seri işlemleri bakımından SQL agregasyonuna birebir eşdeğer kabul edilmemelidir.

Prometheus ağ uç noktaları etkinleştirilirken yetkilendirme ve sorgu maliyeti sınırları diğer API'lerle birlikte ele alınır. Etiket kardinalitesi yüksek metriklerin depolanması, gruplandırma ve harici istemcilerin sorgu frekansı sistem kapasitesinin ayrı bileşenleridir. Kaynak: https://clickhouse.com/blog/clickhouse-release-26-09.

## Ünite 26: Oracle, Debezium, Kafka ve ClickHouse ile Değişiklik Verisi Yakalama (CDC)

CDC hattında asıl problem yalnız veri taşımak değildir; sıra, ofset, en az bir kez teslim, yinelenen olay ve kaynak işlemi ile analitik model arasındaki semantik korunmalıdır.

![Oracle Kafka ClickHouse CDC animasyonu](https://alikoker.com.tr/svg/cdc-oracle-kafka-clickhouse.svg "Oracle Kafka ClickHouse CDC hattı")


Oracle → ClickHouse akışında CDC, kaynak Oracle verisinin yalnız başlangıç kopyasını almak değil, işlem onayı sonrası değişikliklerini sıralı ve doğrulanabilir biçimde taşımaktır. Oracle redo/archived redo günlükleri, SCN ve işlem sınırları bu akışın temelidir. Debezium, GoldenGate, Kafka Connect gibi bileşenler değişiklikleri mesaj akışına taşıyabilir. Ancak ClickHouse'un analitik veri modeli OLTP tablo satırlarını birebir kopyalamak yerine olay geçmişi, son sürüm veya agregasyon biçimlerinden birini açıkça seçmelidir.

CDC üzerinden veri geçişinin doğruluğu için yalnız gecikme metriği yeterli değildir. Kaynak Oracle tablosundan alınan anlık görüntü belirli bir SCN'ye bağlanmalı; bu kesitten sonraki işlem onayları hiçbir boşluk oluşmadan akışa dahil edilmelidir. Bağlayıcı değişiklikleri Kafka'ya en az bir kez teslim ediyorsa ClickHouse'da tekrar gelen olaylar son durum tablosunu veya agregasyonları bozmayacak biçimde ele alınmalıdır. Bir UPDATE, önceki değerlerle yeni değerleri taşıyabilir; hedefe yazılan kolonların anahtar eşleştirmesi eksikse yanlış satır güncellenebilir. Oracle tablo yapısında benzersiz anahtar bulunmaması bu problemi daha karmaşık yapar. XStream yolunun GoldenGate lisansı gerektirebileceği, LogMiner yönteminin Oracle yükü ve connector işlemleri tamponlama seçenekleri bulunması bir maliyet ve operasyon farkıdır. Debezium lisansını GoldenGate ile değiştirerek sıfır altyapı maliyeti varsaymak yanlıştır.

### 26.1. Oracle Yeniden Yapma Günlükleri, SCN ve LogMiner

Oracle redo kayıtları değişikliklerin kurtarma ve çoğaltma için izlenmesini sağlar; SCN mantıksal sıralama ve kesim noktalarında kullanılır. Archived redo'nun saklanma süresi CDC kopması sonrası yeniden okuma kapasitesini sınırlar. LogMiner'ın performansı ve kısıtları Oracle sürümü ve log yapılandırmasına bağlıdır.

Oracle redo günlükleri onaylanan ve henüz işlem onayı edilmemiş değişikliklere ait düşük seviyeli kayıtlar içerir; CDC bağlayıcısı işlem sınırlarını ve işlem onayı konumunu çözümleyerek olayları yayımlar. SCN veri kesitlerinin sıralanmasında yararlı kaynak konumudur. Archived redo saklama süresi yeterli değilse uzun kesintiden sonra kesintisiz devam edilemeyebilir. LogMiner sorgularının CPU, I/O ve undo baskısı büyük kaynak sistemlerde ayrıca test edilmelidir.

### 26.2. GoldenGate, Debezium, XStream ve OpenLogReplicator

GoldenGate ticari replikasyon ve CDC çözümüdür; Debezium açık kaynak connector ekosistemi sunar. Debezium Oracle kaynaklarında LogMiner, XStream veya OpenLogReplicator üzerinden değişiklik okuyabilir; seçenekler aynı lisans ve operasyon gereksinimini taşımaz. Özellikle XStream kullanımında Oracle GoldenGate lisanslama koşulları ayrıca değerlendirilir. “GoldenGate kaldırıldı, tüm senaryolar ücretsiz oldu” sonucu bağlayıcı arayüz ve lisans ayrımları doğrulanmadan çıkarılamaz.

Oracle LogMiner tabanlı okuma, redo kayıtlarının çözümlenmesi ve işlem sınırlarının doğru yeniden kurulmasıyla ilişkilidir. XStream yolu farklı bir Oracle arayüzü ve lisans koşulu taşır; Debezium'un açık kaynak olması XStream'in Oracle tarafındaki lisans yükümlülüğünü kaldırmaz. OpenLogReplicator ayrı bir log okuma altyapısıdır ve seçilmesi hata sonrası toparlanma, izinler ve işlev uyumluluğu yönünden bağımsız sınama gerektirir.

Karşılaştırmanın ölçütü yalnız gecikme olmamalıdır: yeniden başlatma sonrası son işlenen SCN'nin korunması, büyük transaction'ların bekletilmesi, DDL değişikliklerinin işlenmesi, LOB desteği, silinen satırın hedefte temsil edilmesi ve Kafka anahtar bölümlendirmesi doğrudan doğruluk koşullarıdır. Ticari GoldenGate yerine açık kaynak bileşen kullanmak lisans giderini azaltabilir; depolama, Kafka broker ve işletim sorumluluğunun sıfırlanmasını sağlamaz.

Debezium Oracle bağlayıcısının adapter yetenekleri ve sınırlamaları için Debezium Oracle Connector dokümantasyonu esas alınmalıdır: https://debezium.io/documentation/reference/connectors/oracle.html.

### 26.3. Oracle Ek Günlükleme ve Anlık Görüntü

Supplemental logging, güncellenen/silinen satırın hedefte bulunması için gereken eski anahtar alanlarının log'da bulunmasını sağlar. Anlık görüntü akıştan önce alınan taban veri kümesidir. Başlangıç SCN ve anlık görüntü sonrasında oluşan transaction'ların ne şekilde yakalandığı mutlak doğruluk için önemlidir.

Oracle'da CDC, redo kayıtlarının olay olarak yeniden üretilmesiyle çalışır. Bir anlık görüntü alınırken kaynağa yeni işlem onayları gelmeye devam edebilir. Doğru başlangıç için anlık görüntünün tutarlılık sınırı (`SCN`) ile redo akışının başlangıç sınırı uyumlu tutulur. Aksi halde anlık görüntü sonrasında fakat stream öncesinde onaylanmış olaylar kaybolabilir veya snapshot'ta görünen olaylar yeniden akışta tekrar edebilir. CDC tüketicisi bu durumları yalnız “gecikme az” ölçüsüyle ayırt edemez.

Supplemental logging, redo'da değiştirilen kayıtları tanımlamak için gereken alanların bulunmasına yardımcı olur; hangi sütunların loglandığı ve eski/yeni değerlerin hangilerinin sağlandığı yapılandırmaya bağlıdır. Oracle kaynak şemasında fiziksel mükerrer kayıtlar veya anahtarsız tablolar bulunabilir. Böyle bir tabloda DELETE/UPDATE olayını ClickHouse'taki tek bir mantıksal satırla eşlemek her zaman mümkün değildir. “Her tabloda birincil anahtar bulunur” varsayımı CDC tasarımında güvenilirlik açığıdır. Fiziksel satır kimliği yalnız ilgili bağlayıcının ve sürümün gerçekten desteklediği modelde kullanılabilir; bütün şemalara genellenmez.

Oracle kaynak şemasında supplemental logging etkinliği, loglardan anahtar alanların ve güncellenen satırın gerekli eski değerlerinin çıkarılabilmesini etkiler. İlk anlık görüntü alınırken CDC akışının hangi SCN'den başladığı kaydedilmelidir. Anlık görüntü ile akış işleme sınırı yanlış kurulursa aynı işlem iki defa veya hiç yansımayabilir. Büyük tablo anlık görüntüsünün Oracle üzerinde I/O ve undo kullanımına etkisi ayrıca ölçülmelidir; log madenciliği kaynak sistemden bedelsiz veri okumaz.

### 26.4. Kafka Connect, Konu Şeması ve Ofset Yönetimi

Kafka Connect kaynak bağlayıcı değişiklikleri topic'lere taşır; broker topic bölümleri global tek sıralama garantisi vermez. Key seçimi aynı mantıksal satırın aynı bölüme düşmesini sağlayabilir. Offset işlem onayı ile ClickHouse INSERT onayı farklı sistemlerde tutulduğundan tekrar oynatma sınırları belirlenir.

Kafka topic bölümlemesi olayların sıra garantisini belirler: aynı bölüm içindeki kayıtların sırası korunurken farklı bölümler için global toplam sıralama yoktur. Anahtar seçimi aynı kaynak kayıt kimliğinin aynı bölüme yönlendirilmesine yardımcı olabilir. Kafka Connect offset işlem onayı'i ve ClickHouse'taki kalıcı insert atomik bir işlem olmayabilir. Tam doğru yeniden oynatma için olay kimliği veya kaynak SCN/işlem konumuna dayanan tekilleştirme stratejisi gerekir.

### 26.5. Kafka Veri Alımı, Ofset, Parti ve Hata Sonrası Kurtarma

Kafka topic/bölüm offset'i ile ClickHouse INSERT sonucunun ayrı sistemlerde olması uçtan uca atomiklik sorunu doğurur. Yeniden başlatma halinde parti tekrar gelebilir. Consumer offsets, tekrar koruması, Kafka motoru ve MV hedefleri birlikte sınanmalıdır.

Kafka veri alımı hattının hata senaryosu incelensin: ClickHouse hedef INSERT'i kalıcı biçimde kabul eder, fakat consumer ilgili Kafka offset'ini işlem onayı etmeden kapanır. Restart sonrası aynı kayıt yeniden gelir. Bu, en az bir kez teslim sisteminin beklenen davranışıdır. Veri doğruluğu için her CDC olayının kimliği ve hedefte bu kimliğin nasıl ele alındığı belirlenmelidir; tek başına yeniden deneme sayısını azaltmak doğruluk garantisi değildir. Tersi sırada offset başarıyla işlem onayı edilip hedef INSERT başarısız olursa veri kaybı penceresi doğar; offset işlem onayı politikası bu nedenle önemlidir.

Kafka'dan ClickHouse'a akışta bir topic bölümü içinde offset sıralı olabilir; farklı bölümler arasında küresel toplam sıra bulunmaz. Bir tüketici partiyi ClickHouse'a yazdıktan sonra Kafka offset'ini işlem onayı edemeden çökerse aynı parti yeniden işlenebilir. Önce offset işlem onayı edilip sonra yazma tamamlanamazsa veri kaybı riski doğar. Uygun teslim sırası ve idempotency/tekilleştirme sözleşmesi en az bir kez işleme davranışını güvenilir kılar; yazılan her satırın kendiliğinden exactly-once saklandığı varsayılamaz.

ClickHouse Kafka motorundan hedef MergeTree tablosuna materyalleştirilmiş görünüm aktarımı yaygın bir topolojidir. Ancak ara akış kesintileri, ayrıştırma hataları, hedef tabloya yazım sorunları ve geri dolum (geçmiş veri yüklemesi) senaryoları izlenmelidir. DLQ veya hata havuzu gibi yaklaşımların kullanımı, olayların sessizce kaybolmasını engellemek açısından önemlidir. Tüketici lag metriği Kafka tarafında, hedefte görünürlük ClickHouse tarafında, kaynak işlem onayı'ine göre gecikme ise uçtan uca ölçülür; bu üç ölçü aynı değildir.

### 26.6. Anlık Görüntü ve Akışla İşlem Sırası Koruma

Anlık görüntü ile akış işleme arasında boşluk oluşursa olay kaybı, aynı aralık iki kez işlenirse mükerrer olaylar görülebilir. İşlemleri tamponlama kaynak işlemindeki değişikliklerin işlem onayı bütünlüğünü korumaya yardımcı olabilir. Çok tablolu analitik raporlamada ortak tutarlı SCN kesiti veya watermark gerekebilir.

CDC mutabakatında N₀ başlangıç anlık görüntü satırı, I yeni INSERT olayları, D silinmiş mantıksal kayıt sayısı ve U yalnız güncelleme olayları olsun. Tekil kimlikleri korunmuş bir son-durum modelinde N_son = N₀ + I − D beklenebilir; U satır adedini değiştirmez. Ancak fiziksel append-only changelog tablosunda U ve DELETE de yeni olay satırları üretebilir; bu nedenle `COUNT(*)` eşitliği geçerli değildir. Mutabakat formülü hedef tablo semantiğine göre seçilmelidir.
```text
Oracle redo + SCN
       ↓
Debezium LogMiner / XStream / OpenLogReplicator
       ↓
Kafka topic + offset + schema history
       ↓
ClickHouse ham değişiklik günlüğü
       ↓
Son durum modeli / zaman serisi / agregasyon
```
İlk yüklemede anlık görüntü bitiş SCN'si ile canlı akışın başlangıç konumu açıkça izlenir. Güncel CDC belgelerinde LogMiner için uncommitted-change buffering ile database-düzey committed-change işlemenin ayrı maliyet ve bellek davranışı bulunduğu belirtilir. Kaynak Oracle'da LogMiner yükünün azalması connector'da daha fazla işlem tampon belleği gerekmesine yol açabilir.

Kaynak işlem birden fazla tabloya yazabilir; Kafka üzerinden her tablonun ayrı topic'e dağıtılması, tüketim sırasının tablolar arasında kendiliğinden korunacağı anlamına gelmez. Kafka sıralaması ilgili bölüm içinde korunur. Değişikliklerin aynı entity'ye ait olması durumunda kararlı bölüm key seçimi aynı entity'nin olaylarını sırada tutmaya yardımcı olabilir. Kaynak işlem onay sırası farklı topic'lerde bağımsız ilerlediğinden çok tablolu analitik anlık görüntü için ya üst düzey watermark ya da uygun işlem üstveri gerekir.

İlk anlık görüntünün SCN sınırı `s₀`, ClickHouse'a uygulanmış güvenilir en son konum `s₁` ve Oracle'daki güncel işlem onayı konumu `s₂` olsun. Sadece `s₂−s₁` farkı zaman gecikmesi değildir; SCN değerleri zaman birimi olarak yorumlanamaz. Kaynak ve hedefteki aynı iş sözleşmesine uygun checksum/sayım, belirli bir SCN'ye dek tamamlanma ve uçtan uca olay gecikmesi ayrı metriklerdir. Bir INSERT'in ClickHouse'ta görünmesi, aynı kaynak işlemin ilişkili diğer tablo değişikliklerinin de geldiğini tek başına ispatlamaz.

Oracle başlangıç kopyası ve akış işleme arasındaki geçiş, anlık görüntü satırlarının hangi kaynak işlem onayı durumunu temsil ettiğini tanımlamalıdır. Aynı anda çalışan OLTP işlemlerini sebebiyle bir satır snapshot'ta eski sürümüyle okunurken ona ait UPDATE akışı daha önce Kafka'ya ulaşmış olabilir. Debezium'un artımlı anlık görüntü mekanizması, eşleşen kaynak anahtarları üzerinde anlık görüntü penceresi içindeki READ ve streamed olayların çakışmalarını özel tamponlama mantığıyla çözer. Bu davranış hedef veritabanı tarafındaki bağımsız INSERT tekilleştirmesiyle eşdeğer değildir.

Kafka sıralaması bir topic bölümü içerisinde geçerlidir; aynı işlemin farklı tablolara ilişkin mesajları farklı topic veya partition'larda bulunduğunda tüm akış için tek küresel sıra kendiliğinden korunmaz. Bu nedenle çok tablolu rapor mutabakatında işlem onayı konumu, işlem kimliği ve gerekli konu kümelerinin ilerleme eşikleri birlikte izlenir. Kaynak: https://debezium.io/documentation/reference/connectors/oracle.html

Anlık görüntü sırasında Oracle kaynağı işlem almaya devam ediyorsa tablo tablo yapılan sıradan kopyalama, tüm tablolarda aynı SCN kesitini temsil etmez. Anlık görüntü tamamlanmadan açılan CDC akışı aynı satırları tekrar gönderebilir; çok geç başlatılırsa arada onaylanan değişiklikler kaçırılabilir. Kaynak veri kümesinin tanımlanmış bir SCN noktasına göre tutarlı kesiti ve bu noktadan sonraki redo dizisi birlikte tutulmalıdır.

Hedefte veri doğrulaması yalnız toplam satır sayısıyla yapılamaz. Bir satırın güncellenmesi, birinin silinip başka birinin eklenmesi gibi olaylar toplam sayıyı değiştirmeden veri içeriğini farklılaştırabilir. İş anahtarına göre son sürüm, olay sayımının dönemsel kırılımı ve kaynak SCN watermark'ı izlenmelidir. Kafka offset'i, Oracle işlem onayı SCN'si ve ClickHouse INSERT tamamlanması birbirinden farklı ilerleme göstergeleridir.

### 26.7. UPDATE/DELETE Olaylarını ClickHouse Modeline Aktarma

Oracle UPDATE olayını ClickHouse'a yeni versiyon olarak INSERT etmek append-only geçmiş sağlar; son durum tablosu için ReplacingMergeTree, mutation veya düzenli anlık görüntü kullanılabilir. Kaynak DELETE olayı tombstone/`deleted` sürümü olarak taşınabilir. İş alanı benzersizliği bulunmuyorsa eski fiziksel satırın hangisiyle eşleştirileceği belirsizleşebilir; sahte anahtar üretmek doğruluğu kanıtlamaz.

Güncelleme olayının ClickHouse'ta aynı satırın fiziksel olarak değiştirilmesi zorunlu değildir. Olaylar `(kimlik, sürüm, silindi)` biçiminde tutulup en yüksek sürüme göre güncel görünüm hesaplanabilir. Bu yaklaşımda geç gelen düşük sürümlü olay yeni değeri bastırmamalıdır. Silme olayı tombstone olarak korunabilir; fiziksel silme talebi ve düzenleyici saklama kuralı bundan ayrıdır. Kullanıcı raporu tarihsel olayları mı yoksa yalnız en son durumu mu göstereceğine göre sorgu tasarımı değişir.

### 26.8. En Az Bir Kez Teslim, Tekilleştirme ve Veri Doğrulama

At-least-once teslim bir olayın tekrarlanabileceği, kayıp olmadığının ise tek başına garanti edilmediği belirli sözleşmeye işaret eder. Dedup anahtarı kaynak işlem onayı kimliği, işlem sıra numarası ve olay içi sıra gibi alanlardan türetilmelidir. Kaynak/hedef count, checksum veya alan bazlı mutabakat raporu doğrulamanın parçasıdır; hash eşitliği tek başına bütün veri türlerini kanıtlamaz.

CDC taşımasında “exactly once” iddiası üç farklı aşamada incelenmelidir: bağlayıcının redo konumu, Kafka'ya yayın işlemi ve ClickHouse'a kalıcı yazım. Bir aşamada at-least-once teslim yapılması, hedefte mantıksal çoğaltmanın mutlaka engellendiği anlamına gelmez. Hedef tablo tekilleştirme işlemini sürüm ve anahtar üzerinden sağlayabilir; ancak anahtarın doğru seçilmesi, birden fazla sürümün eşzamanlı görünmesi ve birleştirme zamanlaması doğruluğu etkiler.

Örnek bir doğrulama sözleşmesi, her kaynak olay için `(source_table, business_key, source_commit_position, operation)` alanlarını kapsar. `source_commit_position` yalnız SCN ile her satırın benzersiz sıralanmasını garanti etmiyorsa işlemsel iç sıra da gerekir. Anlık görüntü ve akış işleme ayrımında çift işleme tehlikesi, kaynak ve hedef sayılarının aynı çıkmasıyla ortadan kalkmaz: bir satır eksik, başka biri iki kez yazılmış olabilir. Bunun için örneklenen anahtarlar, sürüm durumları, olay toplamları ve yeniden oynatım testleri birlikte yapılmalıdır.

At-least-once delivery, kaynağın onaylanmış olayını yeniden teslim edebilmesi anlamına gelir; exactly-once nihai sonuç elde etmek için hedef yazma ve yeniden oynatma sınırlarında ek idempotency gerekir. Aynı kimlik için farklı olay sürümleri varsa sadece `DISTINCT` uygulamak güncellemenin önce-sonra bilgisini kaybettirebilir. Veri doğrulamasında kaynak ve hedef satır sayısının yanında belirli kaynak işlem konumuna kadar olay kimlikleri ve sürüm dağılımı karşılaştırılır.

At-least-once teslim altında aynı Kafka mesajı başarısızlık sonrasında yeniden işlenebilir. Tüketici offset'i ancak hedef yazımın kalıcılığı doğrulandıktan sonra işaretlenmelidir; ancak offset işlem onayı'i ile ClickHouse INSERT'i farklı sistemlerde ayrı işlemler olduğundan bu sıra, aradaki çöküş penceresinde fiziksel yinelenme ihtimalini tamamen kaldırmaz. Bu pencereyi kapatan yaklaşım, hedefte kalıcı ve kararlı iş kimliğiyle idempotent uygulama yapmaktır.

Olay doğruluğunun kontrolü `COUNT(*)` karşılaştırmasından ibaret olmamalıdır. Gün, kaynak tablo ve olay türüne göre karşılıklı sayım; `max(source_scn)` ilerlemesi; anahtar başına son sürüm; silinmiş kayıtların mantıksal durumu; daha sonra yeniden teslim edilmiş mesajlar ve kaynak aralıklarının boşluksuz işlenmesi ayrı sınanır. Veriyi fiziksel olarak iki kez depolayıp sorguda `uniq(event_id)` ile tekil saymak, kaynak–hedef doğruluk kusurunu görünmez hale getirebilir.

### 26.9. Geçmiş Veri Yükleme, Şema Evrimi ve Hata Sonrası Kurtarma

Geçmiş veri yüklemesi tarih aralığı ve SCN kesim noktası tanımlanmadan yapılırsa canlı akışla çakışabilir. DDL evolution kolon ekleme, tür değişimi, rename ve drop için farklı uyumluluk riskleri doğurur. CDC connector'ın şema history verisi de kurtarma planına katılmalıdır.

CDC kaynak şemasında bir alanın türü `NUMBER`dan daha geniş aralığa taşınabilir veya metin sütununun uzunluğu büyüyebilir. ClickHouse hedefindeki sabit `Int32` gibi dar türler sessiz dönüşüm veya hata riski oluşturabilir; DECIMAL ölçeği para hesaplarında ayrıca korunmalıdır. Tarih ve saat alanlarında Oracle `DATE`, `TIMESTAMP WITH TIME ZONE` ve ClickHouse `DateTime64` dönüşümleri açık zaman dilimi sözleşmesiyle yapılmalıdır.

Geri yükleme için önce tarihsel aralıkların hangi SCN/anlık görüntüyü temsil ettiği tanımlanır. Geçmiş veri yüklemesi ile canlı CDC eşzamanlı çalışırken yazımların birbirinin üzerine nasıl oturacağı versiyon/işlem onayı kimliğiyle belirlenir. Kaynakta silinmiş bir kayıt geçmiş veri yüklemesi ile hedefe tekrar yazılmamalıdır. Mutabakat yalnızca toplam satır sayısıyla değil, dönem ve anahtar düzeyindeki karşılaştırmalarla yapılır. Oracle redo saklama süresi dolarsa CDC'nin eksik aralığı yalnız aynı offset'i yeniden isteyerek tamamlaması mümkün olmayabilir; yeni anlık görüntü ya da sağlam arşiv kaynakları gerekir.

Geçmiş veri yüklemesi sırasında hedefin bir bölümünü yeniden yüklemek, devam eden CDC akışıyla çakışabilir. Kesit sınırını kaynak SCN, olay zamanı veya açık veri hattı watermark'ı ile tanımlamak gerekir. Şema evriminde yeni sütunun eski olaylar için varsayılan değeri bulunabilir; bu değerin gerçek ölçüm sayılması yanlış istatistik üretir. Kafka'daki olay saklama süresi geri yükleme için yeterli değilse kaynak anlık görüntüye dönülmesi gerekebilir.

CDC yeniden başlatılırken önceki offset veya SCN'den itibaren olayların yeniden okunması tipik olarak en az bir kez teslim semantiği doğurabilir. Kaynak `UPDATE` olayının hedefine iki kez uygulanması, fiziksel olarak iki sürüm kaydı üretebilir; `ReplacingMergeTree` kullanıldığında aynı `(iş_anahtarı, sürüm)` çiftinin tekrarı ve aynı sürümde farklı değer gelmesi ayrıca ele alınmalıdır. `version` alanı tek başına kaynak işlem sırasının doğru temsil edildiğini kanıtlamaz.

Geri doldurma işlemi, yalnız belirli tarihlerdeki eksik satırları eklemek değildir. Zaman aralığındaki başlangıç ve bitiş SCN'si, anlık görüntü kesiti, silinmiş kayıtlar, sonradan değişmiş boyut değerleri ve ilgili materyalleştirilmiş görünüm özetleri birlikte ele alınır. Mutabakat, satır sayısı yanında anahtar düzeyinde karşılaştırma ve ölçüm toplamlarının kontrolüyle yapılır. CDC hattı tekrar çalıştırılmadan önce beklenen olay kimliği sözleşmesi değişmemelidir.

### 26.10. İşlemsel Veri Kaynağı ve Analitik Yük İzolasyonu

Oracle ana yazma yolunun sahibi olmaya devam ederken ClickHouse analitik sorgu yükünü ayrıştırabilir. Bu tasarım Exadata'nın işlem kaynaklarını koruyabilir, ancak kaynak redo üretimi, connector okuması ve anlık görüntü taramaları sıfır maliyetli değildir. Geçiş kararı karşılaştırmalı kaynak CPU/I/O ve uçtan uca gecikmeyle verilmelidir.

Oracle kaynak işlemsel doğruluğun kanonik sistemiyse ClickHouse sonuçları bu kaynaktaki belirli kesitin analitik yansıması olarak yönetilir. CDC'nin kaynak üzerindeki log okuma maliyeti ile ClickHouse'un devraldığı rapor yükü birlikte ölçülür. Exadata'dan ayrılan sorgu yükünün yeni sistemdeki CPU/disk ve Kafka operasyon maliyeti raporlanmalıdır. Analitik raporun tazeliği sınırlandırılırken kaynağın işlem izolasyonu özellikleri hedefe kendiliğinden aktarılmış sayılmaz.

## Ünite 27: Sunucu Yapılandırması ve Kaynak Yönetimi

ClickHouse server ayarları birbirinden farklı scope'larda uygulanır: sunucu genel yapılandırması, kullanıcı profili, oturum ve sorgu düzeyi ayarlar aynı önceliğe sahip değildir. Kaynak limitleri kontrolsüz verildiğinde tek bir sorgu bellek, CPU veya disk I/O kaynağını tüketip diğer sorguların gecikmesini yükseltebilir. Ayar değişikliği yalnız hata mesajını kaldırmak için yapılmamalı; kapasite ve kabul edilebilir iş yükü sınırıyla ilişkilendirilmelidir.

Tek sunucuda yürüyen beş karmaşık JOIN sorgusu büyük bellek kullanırken aynı anda düşük gecikmeli API isteklerinin çalışması kaynak izolasyonu sorunudur. `max_memory_usage` benzeri limitler aşırı büyümeyi sınırlarken bu limite ulaşan işlerin başarısızlık politikasını da belirler. Sorgu complexity limitleri beklenmedik tam taramayı durdurabilir; ancak hatanın iş uygulamasına hangi semantikle döndüğü önemlidir. Settings profiles ile farklı kullanıcı sınıfları için sorgu limitleri tanımlanabilir. İş yükü scheduler CPU ve I/O kaynağı için ayrım sağlayabilir, fakat her sürümde aynı ayarların bulunması varsayılmamalıdır. Operasyonun temel metriği tek bir sorgunun en hızlı süresi değil, farklı iş sınıflarının kaynak baskısı altındaki sürdürülebilir davranışıdır.

### 27.1. XML/YAML Yapılandırma Birleştirme, Ortam Değişkenleri ve Gizli Bilgiler

XML/YAML yapılandırma, dosya birleştirme ve ortam değişkenleri sunucu başlatma davranışını etkiler. Secret değerlerinin log'larda ve repo dosyalarında bulunmaması gerekir. Canlı dosya değişikliği ile restart gereksinimleri ayar bazında belirlenir.

Sunucu yapılandırmasında farklı dosyalardan gelen ayarların birleştirilmesi ve profile düzeyinde üzerine yazılması nihai değeri belirler. Ortam değişkeninden alınan parola veya token'ın süreç listesi, hata kaydı ve destek arşivlerinde istemeden görünmemesi gerekir. Kaynak dosyada yapılan değişikliğin çalışan süreçte yeniden yüklendiği varsayılmamalı; yeniden başlatma veya dinamik reload davranışı ayar bazında doğrulanmalıdır.

ClickHouse yapılandırmasında sunucu düzeyi ayarlarla kullanıcı profiline bağlı sorgu ayarları farklı kapsamda uygulanır. `config.xml`, `config.d` ve kullanıcı profili dosyalarının birleştirilme ve üzerine yazılma kuralları tanımlanmadan aynı anahtarın birden fazla dosyada bulunması yanlış değerlendirilir. Üretimde ayarların fiili durumunu `system.settings` ve uygun sistem tablolarından okumak, yalnız kaynak yapılandırmaya bakmaktan daha güvenilirdir.

Ortam değişkeniyle sır taşıma, onu otomatik koruma altına almaz. Proses environment, konteyner tanımı, yedekleme çıktısı ve hata raporları farklı sızıntı yüzeyleridir. Sunucu yeniden yükleme işlevinin bütün ayarlar için geçerli olmadığı kabul edilerek kritik konfigürasyon değişiklikleri sürüm uyumlu yeniden başlatma ve sağlık denetimiyle eşleştirilir.

### 27.2. Ayar Kapsamları, Öncelikler, Profiller ve Kısıtlar

Settings profile default değerleri, kullanıcı bazında ve sorgu bazında özelleştirmeler sağlayabilir. `SETTINGS` ifadesinin bir profile constraint'i aşabildiği varsayılmamalıdır. Değerlendirmede `system.settings`, users ve profiles katalogları kullanılır.

Kullanıcı oturumunda etkili ayarların okunması:

```sql
SELECT name, value, changed
FROM system.settings
WHERE name IN ('max_threads', 'max_memory_usage', 'max_execution_time');
```

Bu değerlerin kaynağı kullanıcı profili, oturum veya query-düzey override olabilir; yalnız değer sorgusu ayarın neden seçildiğini açıklamayabilir.

Ayarlar farklı kapsamlarla uygulanabilir: sunucu genel yapılandırması, kullanıcı profili ve sorgu düzeyindeki `SETTINGS` ifadeleri aynı davranışı etkileme potansiyeline sahiptir. Bir ayarın değiştirilmesine kullanıcının yetkisi olması ve sınırlarının profile/constraint düzeyinde tanımlanması gerekir. Böylece tek bir analitik istemci sınırsız `max_memory_usage` veya `max_threads` değeriyle diğer iş yüklerini etkileyemez. Ayarların sürümler arası isim ve varsayılan değişiklikleri, tekrar üretilebilir başarım karşılaştırması sonuçları için sunucu sürümüyle birlikte kayıt altına alınmalıdır.

Belirli bir ayarı sadece performans deneyi amacıyla sorgu seviyesinde değiştirmek, üretimde sistem geneline yayılmış kalıcı bir yapılandırma değişikliğinden daha kontrollüdür. Ancak bir SQL içindeki `SETTINGS` bloğunun optimizer seçimlerini değiştirmesi, iki ölçümün yalnız tek değişkene sahip olduğunu göstermez; farklı plan, önbellek ve birleştirme koşulları da sonucu değiştirmiş olabilir. Kullanıcı, rol ve profil ayarlarının etkin değerleriyle amaçlanan güvenlik sınırları karşılaştırılmalıdır.

### 27.3. Kotalar, Salt Okunurluk, Allow_ddl ve Karmaşıklık Sınırları

Quota zaman penceresinde tüketimi, sorgu complexity limitleri satır/bayt/bellek sınırlarını kontrol edebilir. Readonly kullanıcı DDL ve veri değiştirme yetkileri sınırlandırılmalıdır. Sınırın hataya neden olduğu koşul verinin gerçekten yanlış olduğu anlamına gelmez; istek bütçesini aştığı anlaşılır.

Quota, belirli zaman penceresinde kaynak tüketimini sınırlamak için kullanılabilir; `readonly` yazma davranışını, `allow_ddl` ve complexity ayarları ise sorgunun hangi işlemleri yapabileceğini etkileyebilir. Tek bir rolün SELECT iznine sahip olması büyük ve pahalı tarama yapamayacağı anlamına gelmez. Zaman, satır, bellek ve eşzamanlılık sınırları ayrıca tanımlanmalıdır. Bazı ayarların etkisi kullanıcı profili, query-düzey override ve sunucu sürümüne bağlıdır.

### 27.4. Bellek Aşımı ve Sorgu Belleği Eşikleri

Bellek limitleri sorgu ve server bütçesiyle ilişkilidir. Overcommit kontrolü ağır sorguyu seçip sonlandırabilir; böylece tüm sunucunun OOM'a gitmesi önlenebilir. Limit yükseltmeden önce yüksek kardinaliteli toplulaştırma ve external diske taşma seçenekleri değerlendirilir.

Tek bir sorgunun bellek üst sınırı ile bütün eşzamanlı sorguların toplam belleği ayrı kapasite sorunlarıdır. Her sorguya çok büyük sınır vermek host seviyesinde OOM olasılığını büyütür. Diske taşma seçeneği bulunan operatörlerde disk alanı ve I/O gecikmesi hesaba katılmalıdır. Bellek taşmasının kullanıcıya hangi hata koduyla döndüğü ve iptal edilen sorgunun geçici disk dosyalarının temizlenmesi operasyonel denetimin konusudur.

Eşzamanlı q sorgunun her birine m bayt bellek üst sınırı verilmesi, sunucunun q × m belleği gerçekten sağlayabildiğini göstermez. Örneğin 32 eşzamanlı sorgunun her birinin 8 GiB'e yükselmesine izin verilirse teorik toplam 256 GiB olur; işletim sistemi, birleştirme işleri ve işaret önbelleği bu bütçenin dışındadır. QPS ve p99 hedefleri için sorgu giriş kontrolü ile bellek bütçesi birlikte tasarlanmalıdır.

Disk taşması (diske taşma) ile bellek sınırı aşımı her operatörde aynı davranmaz. External toplulaştırma ve external sort için uygun ayarlarla bellek düşürülebilir; karşılığında geçici disk I/O'su ve gecikme artar. Kötü sorgu için bellek sınırını yükseltmek yerine `GROUP BY` kardinalitesi, `JOIN` build tarafı ve filtrelerin erken uygulanması incelenir.

### 27.5. İş Yükü Zamanlama, CPU/G/Ç ve Kaynak Hiyerarşisi

İş yükü scheduling CPU/I/O gibi ortak kaynakları hiyerarşik kuyruklarla ayırabilir. İş yükü sınıfları yüksek öncelikli API sorguları ile uzun rapor sorgularını birbirinden ayırabilir. Her kaynak aynı derecede scheduler tarafından sınırlandırılmayabilir; ölçüm gereklidir.

İş yükü scheduling kaynak paylaşımında öncelik ve oran tanımlamak için kullanılır; çalışma zamanı scheduler'ının desteklediği kaynak türleri ve hiyerarşi sürüme göre değişebilir. “Yazma ve okuma ayrı havuzlara ayrıldı” ifadesi kaynakların gerçekten fiziksel olarak izole edildiği anlamına gelmez; disk ve CPU aynı donanımı kullanmaya devam edebilir. Kaynak bütçesi tasarımında INSERT, birleştirme, mutation, backup, ad-hoc analiz ve API sorgularının yoğun saatleri birlikte değerlendirilir.

Bir iş yüküne tanımlanmış kuyruk veya concurrency limiti, o iş yükünün p95 süresini artırırken diğerinin gecikmesini koruyabilir. Kararın başarısı sistemin toplam işlem hacmi'una ek olarak ayrı sınıflardaki p99 ve veri tazeliğiyle ölçülür. Analitik veri tabanının kaynak ayrımı ile OLTP kaynağının dışarı alınması iki farklı izolasyon düzeyidir; CDC üretim aşamasının kaynak üzerindeki etkisi ayrı incelenir.

26.10, iş yükü düzeyinde FIFO dışında ağırlıklı adil paylaşım (`fair`), en az tüketilmiş hizmet süresi yaklaşımı (`las`) ve öncelik tabanlı zamanlama seçenekleri sunar. Adil CPU paylaşımı, sabit kuyruk süresi garantisi değildir; uzun sorguların sistemde birikimi ve kısa sorguların hızla bitirilmesi birbiriyle çatışabilir. `las` düşük hizmet süresi tüketmiş sorguları öne çıkarmayı hedeflerken `priority` sınıflar arası bekleme dağılımını değiştirebilir. Aynı sistemde kullanıcıya dönük kısa raporlar ve toplu yeniden hesaplama varsa koruma yalnız bağlantı sayısıyla değil CPU/I/O hizmet payı, bellek limiti ve diske taşma bütçesiyle kurulur. Resmi gösterimde 50 eşzamanlı, yaklaşık 1 GB'lık sorgu için diske taşma etkinliğinin başarı oranını artırdığı bildirilmiştir; bu sonuç yalnız gösterilen ayar ve test koşullarıyla ilgilidir. [41]

### 27.6. Sunucu Aşırı Yükü, Bağlantı Sınırları ve Hız Denetimi

Connection caps, server overload kontrolleri ve concurrency limits aşırı yük anında admission control sağlar. Çok sayıda istemcinin aynı anda yeniden deneme yapması koruma mekanizmasını etkisizleştirebilir. Backpressure istemci stratejileriyle birlikte değerlendirilir.

Connection cap ve eşzamanlı sorgu sınırı sisteme giren talepleri denetler; CPU ve disk doygunluğunun kendisini ortadan kaldırmaz. Sınırlama arkasındaki kuyruk dolduğunda istemci tarafında timeout ve yeniden deneme fırtınası görülebilir. Geri basınç tasarımında yeniden deneme aralığı, toplam istek bütçesi ve idempotent sorgu davranışı birlikte tanımlanmalıdır. Çok kiracılı kullanımda ağır bir sorgu ailesinin diğer kullanıcıların p99 gecikmesini yükseltmesi engellenmelidir.

### 27.7. Adlandırılmış Koleksiyonlar, Başlangıç Betikleri ve Sistem İncelemesi

Named collections, dış veri kaynaklarına bağlanırken tekrar kullanılan adres, kullanıcı ve bağlantı parametrelerinin merkezi tanımlanmasını sağlar. Yapılandırmanın merkezi olması tek başına gizlilik sağlamaz: collection tanımını görme, kullanma ve değiştirme hakları farklı risklerdir. Bağlantı parolalarının SQL dosyalarına veya sorgu günlüklerine düşmesi engellenmeli; sunucu üzerindeki yapılandırma dosyaları ve gizli bilgi kaynakları erişim denetimiyle korunmalıdır.

Başlangıç betikleri sunucu açılışına işlemsel bağımlılık ekler. Büyük veri dönüşümü veya uzun süren bir uzak kaynak sorgusunun başlangıçta çalıştırılması, hizmetin hazır duruma geçişini geciktirebilir. Kritik veri işleme işleri sunucu süreç yaşam döngüsünden ayrılarak hata sonrasında tekrarlanabilir biçimde yürütülmelidir.

Introspection ve tanılama arabirimleri, thread yığınları, bellek tahsisleri veya etkin ayarlar gibi hassas operasyon bilgilerine erişebilir. SQL kullanıcı hakları, ağ segmentasyonu ve sunucu işletim sistemi yetkileri bu yüzeyler için birbirini tamamlayan kontrollerdir. Yönetim yüzeyleri yalnız güvenilir erişim bölgelerinden kullanılmalı; uygulama API'sinin erişimi bu yetkileri otomatik olarak içermemelidir.

### 27.8. Çok Kiracılı Sistemler ve Kaynak İzolasyonu

Çok kiracılı sistemde tenant başına kota, rol ve sorgu önceliği tasarlanabilir. Aynı fiziksel part'ta tenant verilerinin tutulması erişim kontrolünün tam uygulandığını otomatik garanti etmez. Tenant isolation hem mantıksal yetki hem kaynak rekabeti boyutuyla ele alınır.

Çok kiracılı analitikte tenant alanının tablo şemasında bulunması tek başına erişim izolasyonu sağlamaz. Kullanıcı bazlı rol ve row-policy koşulları ile sorgu resource quota farklı savunma katmanlarıdır. Bir tenant'ın büyük SELECT'i diğer tenant'ın sorgu gecikmesini yükseltebiliyorsa hesaplama izolasyonu eksiktir. Veri erişim ve kaynak izolasyon testleri ayrı yapılmalı; servis hesabının geniş yönetici yetkisine sahip olması uygulama API'sinde SQL enjeksiyon etkisini büyütebilir.

## Ünite 28: Güvenlik, Yetkilendirme ve Kimlik Doğrulama

ClickHouse erişim denetimi rol, kullanıcı ve nesne yetkilerine dayanır. Üretim mimarisinde ağ erişiminin daraltılması, TLS ile aktarımın korunması, servis hesaplarının en az ayrıcalıkla çalışması ve secrets yönetimi birlikte değerlendirilmelidir. Veritabanına yalnız analitik SELECT yaptırmak istenen servis hesabı mutation, DDL ve yönetim yetkileri almamalıdır.

Veritabanı ağ erişiminin korunması, kullanıcı hesabının şifresinin güçlü olmasından daha geniş bir güvenlik konusudur. Bir istemcinin `SELECT` yetkisi bulunması, kişisel veri satırlarının tümünü görmesi gerektiğini göstermez. Row policy ve role grant sınırları veri sınıflandırmasıyla ilişkilidir. Sertifika doğrulaması kapatılan TLS bağlantısı şifreleme kullansa bile sunucu kimliği güvenini kaybedebilir. Dış LDAP/JWT doğrulama altyapısının kesintisi bağlantı erişimini etkiler; önceden açık oturumların davranışı ayarlarla ilişkili olabilir. Sorgu log'larda hassas SQL literal'lerin kalması arama ve yedekleme yüzeyini genişletebilir. Bu nedenle güvenlik tasarımı ağ, identity, role, audit ve retention katmanları arasında tutarlı olmalıdır.

### 28.1. RBAC Kullanıcıları, Roller, Yetkiler ve Erişim Varlıkları

RBAC kullanıcıları roller üzerinden yetkilendirir; GRANT/REVOKE erişim yüzeyini sınırlar. Kullanıcıya tablo okuma yetkisi verildiğinde ilgili system tables veya dictionary üzerinden dolaylı veri açığı oluşup oluşmadığı da incelenir. Roller zamanla yetki biriktirmemelidir.

Yalnız sorgulama yapması gereken hesaplar için ayrı bir rol oluşturulabilir:

```sql
CREATE ROLE analytics_reader;
GRANT SELECT ON default.events TO analytics_reader;
```

Örnekte gerçek kullanıcı hesabı oluşturulmaz ve kimlik bilgisi tanımlanmaz. Rol üyeliği, ağ erişimi ve gerekli olmayan sistem katalogları ayrıca sınırlandırılır.

Kullanıcı yetkileri sorgu, tablo, veritabanı, dictionary ve belirli ayarlar düzeyinde ayrıştırılabilir. Analitik istemcinin yazma gereksinimi yoksa SELECT yetkisiyle sınırlandırılması, CDC ingest hesabının da yalnız hedef tabloya INSERT yetkisi alması uygun güvenlik sınırlarıdır. `readonly` kullanımını tek başına her türlü veri sızdırma veya kaynak tüketimi engeli saymak doğru değildir; pahalı SELECT sorguları CPU, RAM, disk ve ağ tüketebilir. `max_execution_time`, bellek ve concurrency sınırları RBAC ile birlikte uygulanır.

Dış kimlik doğrulama LDAP veya Kerberos gibi mekanizmalarla yapılabilir; yine de yetki modeli ClickHouse tarafında tanımlanmalıdır. Bağlantı sertifikası doğrulaması, `secure` port ve mTLS varlığı, istemcinin doğru endpoint'e bağlandığının ve sertifikanın güvenilir olduğunun doğrulanmasıyla anlam kazanır. SQL ile yapılandırma ortamındaki gizli bilgilerin sorgu günlüklerine düşmesini engellemek ayrı bir sorumluluktur.

### 28.2. Ağ Bağlantı Noktaları, Dinleme Adresleri ve Segmentasyon

ClickHouse'da istemci sorguları, sunucular arası veri aktarımı, replikasyon koordinasyonu ve yönetim erişimi farklı ağ akışları oluşturur. Native TCP, HTTP/HTTPS, replika aktarımı ve Keeper bağlantıları aynı güvenlik bölgesine açık bırakılmamalıdır. Port numarası ile protokol birbirine karıştırılmamalı; kurulumda etkin dinleme soketleri, yapılandırma ve ağ güvenlik duvarı kurallarıyla doğrulanmalıdır.

TLS, aktarımın gizliliğini ve karşı uç doğrulamasını sağlayabilir; ancak yanlış ağ kuralını veya aşırı geniş SQL yetkisini düzeltmez. Ağ tehdidi üç farklı noktadan değerlendirilir: ağa bağlanabilen kaynaklar, kimliğini kanıtlayabilen istemciler ve doğrulanmış kullanıcının çalıştırabileceği SQL işlemleri. Örneğin yalnız SELECT yetkisine sahip bir servis hesabının sistem tablolarındaki hassas bilgilere veya aşırı maliyetli sorgulara erişimi ayrıca sınırlandırılabilir.

Replikasyon ve Keeper trafiğinin uygulama istemcilerinden ayrılması, tekil bir ağ kesintisinin hangi veri yollarını etkilediğini belirlemeyi kolaylaştırır. Sadece “açık port” sayımı yeterli değildir: yük dengeleme, DNS çözümleme, zaman aşımı, sertifika yenileme ve bağlantı havuzu davranışı da arıza analizinin parçasıdır.

### 28.3. TLS, mTLS, Sertifikalar ve ACME Yaşam Döngüsü

TLS kanaldaki veriyi şifreler ve sunucu kimliğinin doğrulanmasını sağlar; mTLS istemci sertifikası doğrulaması ekler. Sertifika yenileme, CA güven zinciri ve süresi dolmuş sertifika senaryoları operasyon planına katılır. ACME otomasyonu doğrulama ve erişim politikalarıyla ilişkilidir.

TLS sunucu kimliğinin doğrulanması ve taşıma katmanındaki gizliliğin korunmasını sağlar. Sertifikanın yalnız sunulması yeterli değildir; istemci güven zinciri, isim eşleşmesi, süre dolumu ve sertifika iptali politikasını uygulamalıdır. mTLS ek olarak istemci sertifikasıyla kimlik doğrulamayı destekler; yetki denetimi ve sorgu sınırları yine gereklidir. Native TLS, HTTPS ve proxy üzerinden TLS sonlandırma birbirinden farklı güven bölgeleri oluşturur.

Sertifika döndürme planında istemci connection pool'larının uzun süre açık bağlantıları, sunucunun yeniden yükleme davranışı ve yük dengeleme katmanındaki health check politikası değerlendirilir. Sunucu portlarının yalnız ilgili uygulama segmentlerine açılması, test ve üretim ortamlarında anonim veya geniş yetkili bağlantıların engellenmesi saldırı yüzeyini azaltır.

### 28.4. LDAP, Kerberos, JWT ve HTTP Kimlik Doğrulama

LDAP, Kerberos, JWT ve HTTP tabanlı auth seçeneklerinin destek düzeyi sürüm ve yapılandırmaya bağlıdır. Dış kimlik hizmetinin çalışmaması yeni bağlantıları etkileyebilir. Token ömrü ve anahtar rotasyonu kontrol edilmelidir.

LDAP harici kullanıcı dizininden kimlik denetimi ve kullanıcı yönetimine yardımcı olabilir; Kerberos bilet tabanlı doğrulama sunar. JWT kullanan entegrasyonlarda imza doğrulama, issuer, audience ve süre denetimi önemlidir. HTTP tabanlı erişimde Basic veya başlık temelli kimlik bilgileri yalnız şifreli bağlantı ve uygun log maskelemesiyle kullanılmalıdır. Hangi şemanın yerel olarak desteklendiği ClickHouse sürümü ve dağıtımına göre farklı olabilir; genel kimlik protokolü desteği ürün yeteneğiyle karıştırılmamalıdır.

Harici kimlik doğrulama mekanizmaları farklı güven sınırlarına sahiptir. LDAP parolası veya directory doğrulaması ile Kerberos bileti, HTTP harici doğrulayıcı isteği ve JWT imza doğrulaması aynı protokol değildir. Token tabanlı doğrulamada anahtar dağıtımı, audience, issuer, son kullanma ve saat sapması; merkezi dizinde ise bağlantı kaybı, önbellek süresi ve hesap devre dışı bırakmanın yayılımı ayrı tehdit koşullarıdır.

Kullanıcı kimliği başarıyla doğrulansa bile hangi veritabanı, tablo veya sütuna erişebileceği RBAC kurallarıyla belirlenir. Harici doğrulayıcıdan gelen kullanıcı öznitelikleri ile ClickHouse içindeki role/grant eşleşmesinin hangi bileşende yapıldığı ürün sürümüne göre doğrulanmalıdır. Bağlantı kurulurken ve sorgu çalışırken yetki değişiminin etkileri aynı değildir; yönetim tasarımında oturum ömrü ve yeniden doğrulama politikası tanımlanır.

ClickHouse Cloud tarafındaki JWT tabanlı kimlik doğrulama ve SCIM 2.0 kullanıcı/rol yaşam döngüsü bütünleşmesi, self-hosted sunucudaki yerel kullanıcılar ve LDAP/Kerberos ayarlarından ayrı yönetim katmanlarıdır. 26.10 dönemindeki Cloud yeteneklerini OSS kurulumu için koşulsuz kullanılabilir saymak doğru değildir. JWT doğrulamasında imza, `issuer`, `audience`, zaman sınırları ve anahtar döndürme sözleşmesi; SCIM eşitlemesinde ise hesap kapatma, grup üyeliği değişimi ve başarısız eşitleme sonrası yetki iptali davranışı incelenmelidir. Kimlik doğrulama başarıyla tamamlandığında dahi veritabanı rolünün tablo düzeyinde en az yetki ilkesini uygulaması gereklidir. [41]

### 28.5. Harici Kimlik Doğrulayıcılar, SSH Anahtarları ve X.509

X.509 ve SSH key auth farklı protokollerin kimlik doğrulama bileşenleridir. Dış doğrulayıcı yanıtlarına sorgusuz güvenmek doğru değildir; bağlantı güvenliği ve kimlik eşleştirmesi gerekir. Hesap yaşam döngüsü merkezi yönergelerle eşleştirilir.

X.509 istemci sertifikaları makine kimliğinin TLS katmanında doğrulanmasını sağlayabilir; sertifika ortak adı ile veritabanı kullanıcı eşlemesi açık yapılandırma gerektirir. SSH anahtarıyla uzak sunucu yönetimi ve ClickHouse'a SQL düzeyinde kimlik doğrulama birbirinden ayrı işlemlerdir. Harici sağlayıcının geçici erişilemezliğinde mevcut bağlantıların devamı ve yeni oturumların kabulü farklı davranış gösterebilir. Kimlik altyapısı kesintisi de kullanılabilirlik testine dahil edilmelidir.

Sertifika tabanlı kimlik doğrulamada iki bağımsız bağ vardır: TLS karşı tarafın sertifikasını güven zinciri ve geçerlilik süresiyle doğrular; veritabanı ise doğrulanan sertifika kimliğini bir kullanıcıya bağlar. Bu ikinci adım açıkça tanımlanmamışsa şifrelenmiş bağlantı yetkilendirilmiş SQL oturumu anlamına gelmez. Sertifika iptali, CA rotasyonu ve yeni oturum açılışındaki doğrulama yolu da işletim kapsamına girer.

Merkezi LDAP veya başka bir harici kimlik sağlayıcıda bağlantı kopması, yeni oturumların reddedilmesine veya belirli önbellek kurallarının devreye girmesine yol açabilir. Bu olayın, mevcut sorguların tamamını anında sonlandırdığı varsayılmamalıdır. Yönetici erişimi için kullanılan kurtarma hesabının yetkileri, saklanması ve kullanım kayıtları ayrı güvenlik sınırları gerektirir.

### 28.6. TOTP ve Servis Hesabı Yaklaşımları

TOTP ikinci bir doğrulama katmanı olarak değerlendirilebilir; otomasyon hesaplarında etkileşimli ikinci faktör yerine sertifika ve kısa ömürlü hizmet kimliği daha uygun olabilir. Desteklenen seçeneklerin tamamı aynı dağıtımda mevcut kabul edilmemelidir.

Etkileşimli yönetim hesabında ikinci faktör kimlik avı riskini azaltabilir; ancak TOTP'nin belirli ClickHouse dağıtımında doğrudan desteklenmesi ile önündeki kimlik sağlayıcısınca zorunlu tutulması farklıdır. Otomatik veri hattında etkileşimli TOTP istenmesi sürekliliği bozabilir. Servis hesaplarına asgari SQL yetkisi, kısa ömürlü erişim bilgisi ve merkezi iptal olanağı verilmelidir. Kimlik doğrulama yöntemi seçimi, veri hattının yeniden başlatılabilirlik tasarımıyla uyumlu olmalıdır.

### 28.7. Gizli Bilgi Yönetimi ve Parola Riskleri

Parolanın düz metin config, connection string veya log üzerinde tutulması gizli bilgi sızıntısı riskidir. Secret injection, vault erişimi, rotate ve audit mekanizmaları tasarlanır. SQL örnekleri gerçek kullanıcı adı/parola ve sistem adresi içermez.

Şifre, token ve sertifika anahtarı yapılandırma dosyasına açık yazıldığında dosya izinleri dışında anlık görüntü, yedek ve destek paketi sızıntı riskleri de oluşur. Harici sır deposu veya korunan ortam değişkeni kullanılabilir; çalışma zamanı loglarına sırın geçmemesi gerekir. Sır rotasyonunun kesintisiz gerçekleşmesi için yeni ve eski yetkinin sınırlı örtüşme penceresi ve bağlantı havuzlarının yenilenmesi planlanmalıdır. Uygulama ve yönetim hesaplarının sırları aynı yetki alanında tutulmamalıdır.

### 28.8. En Az Yetki İlkesi, Denetim ve Uyum

En az ayrıcalık ilkesi, ayrı admin ve salt okunur hesapları, ağ kısıtları ve değişiklik kaydıyla uygulanır. Veri sınıflandırması kişisel/veri güvenliği gereksinimlerini belirler. Yetki testi yalnız olumlu SELECT değil reddedilen DELETE/ALTER denemelerini de kapsar.

En az yetki ilkesi, kullanıcıya yalnız çalışması gereken tablolar ve fonksiyonlar için izin verilmesini gerektirir. SELECT yetkisi hassas verinin toplu dışarı aktarılmasını da mümkün kılabildiğinden row policies, masking ve sorgu sınırları göz önünde bulundurulmalıdır. Audit kayıtları kullanıcı, sorgu, zaman ve başarısız yetki girişimlerini ayırt edebilmelidir. Yetki değişikliği kalıcı oturumlar ve harici kimlik sağlayıcı önbellekleri açısından da sınanmalıdır.

ClickHouse 26.9 `CREATE TOKEN` aracılığıyla geçerlilik süresi sınırlı kimlik bilgisi oluşturmayı destekler. Token kullanıcının mevcut yetkilerini genişletmez; daha dar bir grant alt kümesine indirgenebilir. Örneğin raporlama servisinin belirli bir tabloyu sadece okuması gerekiyorsa, ana kullanıcı parola ve tüm yetkileri aktarılmadan süreli SELECT yetkili token kullanılabilir. Geçerlilik süresinin bitmesi kadar token'ın kullanıcıdan bağımsız bir kasa sisteminde erişim kurallarıyla saklanması da önemlidir.

```sql
CREATE TOKEN
VALID FOR INTERVAL 30 MINUTE
GRANTS (SELECT ON analytics.events);
```

Bu örnek, çağıran kullanıcıda token oluşturma yetkisinin ve `analytics.events` nesnesinde SELECT erişiminin bulunduğunu varsayar. Token değeri sorgu günlüğüne, terminal geçmişine veya uygulama hata mesajına yazılmamalıdır. 26.9 öncesi sürümlere bu sözdizimi uygulanmaz. Kaynak: https://clickhouse.com/blog/clickhouse-release-26-09.

26.8 ile sunulan `system.user_query_log`, sıradan kullanıcının yalnız kendi sorgu geçmişini incelemesine yöneliktir; tüm kullanıcıların günlüklerine erişim hakkı vermez. Bu ayrım paylaşılan analitik kümelerde hem hata ayıklama hem erişim izolasyonu açısından yararlıdır. Ancak kullanıcının kendi sorgusunu görmesi dahi parametrelerde veya dinamik SQL içinde hassas bilginin yer almaması gereksinimini ortadan kaldırmaz. Log saklama süresi, yetki değişimi, sorgu metninin maskeleme politikası ve mevzuat gereksinimleri ayrıca belirlenir. [46]

## Ünite 29: Yedekleme, Geri Yükleme ve Afet Kurtarma

Yedekleme bir başka replikaya sahip olmakla aynı değildir. Replikasyon mantıksal silme veya bozuk veriyi çoğaltabilir; yedek, belirli bir zaman kesitindeki bağımsız geri yükleme kaynağıdır. ClickHouse BACKUP/RESTORE altyapısı tablo veri veri parçalarını ve uygun metadata'yı taşıyabilir; kapsam ve tutarlılık sürüme göre doğrulanmalıdır. Başarılı yedekleme bildirimi, kurtarma testinin yerine geçmez.

Kurtarma stratejisi yalnız tablo verisinin ikinci kopyasını almak değildir. Büyük data veri parçalarının object store'dan indirilmesi, Keeper ve replica üstverinin yeniden kurulması, sorgu hesaplarının yetkileri ve CDC hattının hangi SCN'den yeniden başlatılacağı planın parçasıdır. Yedekten dönüldüğünde yeni olayların akışla tekrar gönderilmesi geçmişte alınmış bazı verileri mükerrer üretebilir. Kurtarma runbook'unda kaynak anlık görüntü ve hedef checkpoint bilgileri birlikte saklanmalıdır. RPO iş açısından kaybolabilecek veri penceresini, RTO tüm hizmetin geri dönme süresini temsil eder. Backup başarı kaydının varlığı tek başına okunabilir ve tutarlı bir analitik sistemin yeniden kurulduğunu göstermez; restore testi zorunludur.

### 29.1. BACKUP/RESTORE Kapsamı ve Tutarlılık

`BACKUP TABLE db.events TO Disk('backups', 'events-20261027')` gibi sözdizimi tanımlı bir disk yapılandırmasına bağlıdır. Birden çok tablo yedeklenirken aynı uygulama işlem kesitinin yakalandığı varsayılamaz. Kaynak checkpoint ve downstream veri soy ağacı yedek manifestine eklenebilir.

Önceden yapılandırılmış yedek disk hedefi için SQL örneği:

```sql
BACKUP TABLE default.events
TO Disk('backups', 'events_20261027');
```

`backups` adlı disk sunucu konfigürasyonunda bulunmalıdır; bu DDL tek başına uzak saklama veya geri yüklenebilirlik garantisi vermez.

BACKUP/RESTORE komutunun kapsadığı tablolar, üstveri ve erişim varlıkları açıkça belirtilmelidir. Aynı anda değişen çok sayıda tablo için tek mantıksal kaynak kesiti aranıyorsa işlem tutarlılığı ayrıca planlanır. Yedeğin tamamlanmış durumda olması ve hedef konumda gerekli objelerin bulunması kontrol edilir. Sadece backup job'ın başlamasına bakarak kurtarma kapasitesi olduğu iddia edilemez. Periyodik restore testinde sonuç doğruluğu ve kurulumdan sorguya kadar geçen süre ölçülür.

### 29.2. Tam ve Artımlı, Eşzamanlı ve Asenkron Yedekleme

Tam yedek bütün veri kopyasını, incremental yedek önceki durumdan farkları tutmayı hedefler. Incremental zincirinin bir halkası kaybolursa kurtarma başarısız olabilir. Asenkron yedek başlaması ile başarıyla tamamlanması birbirinden ayrılır.

Tam yedek, belirli veri ve üstveri kümesinin başlangıç noktasını oluşturur; artımlı yedek önceki tabana bağımlı olabilir. Yedek zincirindeki tek halkaya erişilememesi geri yükleme olasılığını etkiler. Eşzamanlı olmayan yedek başlatılması işlemin tamamlandığı anlamına gelmez; iş durumu ve uzak hedefteki nesnelerin doğrulanması gerekir. Yedek başlangıç ve bitiş zamanları, veri değişiminin yoğun olduğu sistemlerde kurtarılabilecek kesitin tanımlanmasına yardımcı olur.

Örneğin pazar gecesi tam yedek ve sonraki altı gün artımlı yedek alındığında cumartesi günkü geri yükleme zinciri pazar tabanına ve gerekli artımlı parçalara bağlıdır. Zincirdeki yalnız perşembe nesnesinin bozulması, sonraki yedek dosyaları fiziksel olarak bulunsa bile tutarlı kurtarmayı engelleyebilir. Gerçek bağımlılık, kullanılan ClickHouse yedekleme yöntemi ve incremental referans modeline göre doğrulanmalıdır.

RPO, kayıp kabul edilebilecek veri süresini; RTO, hizmetin geri gelmesi için kabul edilen süreyi belirtir. Saatlik yedek almak otomatik olarak bir saatlik RPO sağlamaz: son yedeğin gerçekten tamamlanmış ve geri yüklenebilir olması gerekir. RTO da yedek boyutuna, uzak depodan transfer hızına, üstveri geri yüklemeye ve sorgu hizmetinin ısınmasına bağlıdır.

### 29.3. Yerel Disk, S3 ve Azure Blob Yedekleme Hedefleri

Yerel disk hedefi, aynı sunucu içinde hızlı yedek yazımı ve geri yükleme sağlayabilir; fakat kaynak veriyle aynı fiziksel arıza alanında bulunuyorsa felaket kurtarma kopyası sayılmaz. S3 veya Azure Blob gibi nesne depoları farklı arıza alanlarında saklama olanağı sunar. Ağ bant genişliği, aktarım ücreti, depolama sınıfı, erişim anahtarı ve nesne yaşam döngüsü politikası toplam maliyetin parçalarıdır.

Geri yükleme süresinin alt sınırı veri boyutuyla bağlantılıdır: 20 TiB yedeğin kullanılabilir aktarım hızı 1 GiB/s ise yalnız veriyi aktarma aşaması yaklaşık 5,7 saat sürer; üstveri kurulumu, yeniden indeksleme veya bağlantı kurulumu bu hesaba dahil değildir. Bu nedenle RTO yalnız yedek alma süresiyle ölçülmez. Artımlı yedekleme kullanılıyorsa temel yedeğin ve artımlı zincirin birlikte erişilebilir olması gerekir; tek bir bağımlılığın silinmesi kurtarma olanağını bozabilir.

Bir yedeğin nesne depoda görünmesi, SQL düzeyinde geri yüklenebilir olduğunu kanıtlamaz. Ayrı bir hedefte şema, tablo sayısı, örnek olay sayımları, sıralama anahtarları, erişim rolleri ve kurtarma noktasının doğrulanması gerekir. Şifreleme anahtarının yalnız kaynak bölgede saklanması, coğrafi olarak ayrılmış yedeği fiilen erişilemez kılabilir.

### 29.4. Dosya Sistemi Anlık Görüntüleri ve Yalnız Üstveriyle Kurtarma

Filesystem anlık görüntü kısa kesitte tutarlı disk görünümü yakalayabilir; ancak dağıtık tablo bütünlüğü ve üstveri koordinasyonu ayrıca gerekir. Metadata-only kurtarma verinin asıl parçalarının ulaşılabilir olmasına bağlıdır. Tek host anlık görüntüyü tüm küme kurtarması değildir.

Dosya sistemi anlık görüntüyü, disk üzerindeki baytların belirli anda görüntüsünü sağlar; ancak uygulamanın tüm üstveri ve dağıtık replica durumlarının aynı kesitte olduğu ayrıca gösterilmelidir. Anlık görüntünün alınmasıyla ClickHouse'un BACKUP komutunun tutarlılık kapsamı birebir aynı değildir. Keeper verisi, erişim yetkileri ve dış sözlük kaynakları gibi bileşenler kurtarma planının dışında bırakılmamalıdır.

Depolama anlık görüntüsü yaklaşımında tekil disk bir anlık bayt durumu verse de ClickHouse üstverisi, arka plan birleştirmeleri ve başka replica'ların yazma durumu bu kesitte aynı olmayabilir. Yedek kapsamı tablo veri parçalarını, tablo şemasını, kullanıcı/rolleri, sözlük tanımlarını, depolama politikalarını ve koordinasyon üstverisini içerip içermediğine göre değerlendirilir. Sadece veri parçası dosyalarını kopyalamak geçerli bir `RESTORE` planı sayılmaz.

Kurtarma testi en az şu doğrulamaları kapsar: beklenen bölüm/veri parçası sayısı, örnek sorgu sonuçları, erişim yetkileri, replikasyon yeniden başlatıldığında veri tutarlılığı, backup alınırken devam eden INSERT'lerin görünürlüğü ve RPO/RTO hedefi. Replikasyon yanlışlıkla silinen bir tablonun kaybını da replikalara taşıyabildiği için bağımsız yedekleme katmanı gerekir.

### 29.5. Yedek Sıkıştırma, Erişim Varlıkları ve Ayarlar

Backup compression depolama alanını azaltırken ek CPU maliyeti yaratır. Users, roles ve diğer access entities de kurtarma kapsamına dahil edilecekse yetki ve gizli bilgi politikaları gözetilir. Restore sırasında eski izinlerin yeni çevrede istenmeden açılması engellenir.

Sıkıştırma yedek boyutunu azaltırken geri yükleme CPU kullanımını etkiler. Yedekte erişim varlıklarının ve ayarların bulunması, yanlış ortamda eski yetkilerin etkinleştirilmesi riskini doğurur. Gizli bilgiler yedek şifrelemesi ve saklama anahtarı politikasıyla korunmalıdır. Veri veri parçalarını kadar tabloların DDL tanımları, sözlükler ve servis yapılandırması da sürdürülebilir geri yükleme için gereklidir.

Yedek sıkıştırması hem aktarılacak baytı hem de geri yükleme CPU süresini etkiler; yedek stratejisinin başarısı sadece oluşturma süresiyle ölçülmez. Örneğin bir kayıtta şema, veri, access entities ve harici sözlük tanımları farklı yaşam döngülerinde saklanıyorsa yalnız tablo part'larının kurtarılması uygulamanın aynı sorgu sonuçlarını üretmesini sağlamayabilir. RPO ve RTO hesaplarında dış kaynak bağlantı bilgilerinin yeniden sağlanması, Keeper koordinasyonu ve sorgu hizmetinin tekrar kabul edilmeye başlaması ayrı aşamalardır.

### 29.6. Replication Yedekleme Değildir Ayrımı

Replica'da mevcut DELETE veya yanlış UPDATE tekrarlandığında her replica aynı hatayı taşıyabilir. Backup retention replikasyon yaşam döngüsünden bağımsız tanımlanmalıdır. Immutable/çevrimdışı anlık görüntü, kötü niyetli veya insan kaynaklı veri kaybına karşı savunma katmanı sağlayabilir.

Replikasyon, sunucu kaybına karşı aynı mantıksal veri kopyasını tutar; yanlış `DROP TABLE`, yetkisiz DELETE, mantıksal veri bozulması ve kötü konfigürasyon değişiklikleri replika tarafına da aktarılabilir. Bu nedenle yedek, replikalardan farklı hata alanında tutulmalı; mümkün olduğunca sürüm ve saklama süresi ile korunmalıdır. Yedekleme stratejisi yalnız restore komutunun başarısı üzerinden doğrulanmaz; geri yüklenen tabloya uygulama sorguları yöneltilerek kayıt sayısı, kritik agregasyonlar ve üstveri yetkileri sınanır.

`RPO` kabul edilebilir en büyük veri kaybı zamanını, `RTO` sistemin yeniden hizmet vermesi için kabul edilen en büyük süreyi temsil eder. Örneğin her gün alınan tam yedek ve saatlik artımlı yedek bulunuyorsa RPO teorik olarak en çok bir saat olarak hedeflenebilir; bunun için artımlı yedeklerin başarıyla tamamlanması, güvenli biçimde saklanması ve bağımlı zincirin sağlam olması gerekir. RTO ise petabayt ölçekli veri transfer süresi, bant genişliği, üstveri kurtarma ve indekslerin okunabilirliğini de kapsar.

### 29.7. RPO, RTO, Bölgeler Arası Kurtarma ve Geri Yükleme Testleri

RPO kabul edilebilir en fazla veri kaybı süresi, RTO hizmetin toparlanma zamanıdır. Anlık görüntü periyodu, CDC kurtarma noktası, object-store aktarım hızı ve tablo büyüklüğü bu hedefleri belirler. Restore provası olmadan teorik RTO değeri operasyon garantisi değildir.

Örnek kurtarma hedefi RPO = 15 dakika, RTO = 60 dakika olsun. Bu hedefler uygulama ihtiyacının varsayımsal değerleridir, ClickHouse ürün garantisi değildir. Saatlik full anlık görüntü tek başına 15 dakika RPO sağlayamaz; daha sık incremental/CDC replay ve kurtarma kesiti gerekir. Restore testi; object-store'dan verinin indirilmesi, Keeper ve replica üstverisinin hazırlanması, tabloların açılması, hakların yüklenmesi, sorguların doğrulanması ve servis yönlendirmesinin tekrar çalışmasını kapsar. Yalnızca dosyaların geri gelme süresi RTO değildir.

### 29.8. Yedek İçeriğinin ve Kurtarmanın Doğrulanması

Backupview ve ilgili araçlar yedek içeriğini inceleyebilir; doğrulama bir kontrol listesini aşmalıdır. Restore edilen satır sayısı, veri parçası checksums, zaman aralığı ve örnek analitik sonuçlar kaynak raporlarla karşılaştırılır. Büyük dataset'te örneklem ve tam tutarlılık testleri farklı kanıt düzeyleridir.

Yedek incelemesi dosyaların mevcut olduğunu gösterebilir fakat geri yüklenen servisin doğru sorgu sonuçları verdiğini kanıtlamaz. Kurtarma testi ayrı ortamda tablo varlığı, row count, tarih aralığı, checksum ve belirli analitik sonuçlar açısından yapılmalıdır. Özellikle agregasyon durumları ve ReplacingMergeTree tablolarında yalnız fiziksel satır sayısı mantıksal görünümün doğruluğunu göstermez. Erişim yetkileri ve kaynak entegrasyonlarının da hedef ortamda çalıştığı sınanmalıdır.

Kurtarma tatbikatında başarı ölçütü “BACKUP komutu çalıştı” değildir. Ayrı bir test ortamına geri yükleme yapılır; tablo şeması, kullanıcı/rol yetkileri, bölüm dağılımı, belirli dönemlerin satır sayıları, toplamsal kontrol değerleri ve örnek sorgu sonuçları kaynak kesitle karşılaştırılır. Yedek alma anından sonraki CDC olaylarının yeniden uygulanması gerekiyorsa başlangıç SCN/offset değeri belgelenir. Yanlış başlangıç, yedek üzerindeki son olayların tekrar eklenmesine veya boşluğa neden olabilir.

Erişim hatası, eksik artımlı yedek parçası, farklı ClickHouse sürümü, anahtar yönetim sisteminin kullanılamaması ve yavaş nesne depolama ayrı hata senaryolarıdır. RTO yalnız verinin diske açılması değil, sorgu hizmetinin doğruluk kontrolünden sonra kabul edilebilir gecikme düzeyine dönmesidir. Kurtarmanın düzenli deneylerle ölçülmesi bu nedenle gereklidir.

## Ünite 30: Sistem İzleme, Performans Tanılama ve Sorun Giderme

Kaynak kullanımı kapasiteye yaklaştıkça ortanca gecikmeden önce kuyruklanma ve kuyruk gecikmesi büyür; bu nedenle p95 ve p99 değerleri doygunluğu daha erken gösterebilir.

![Sorgu gecikmesi ve doygunluk animasyonu](https://alikoker.com.tr/svg/query-latency-saturation.svg "Sorgu gecikmesi ve doygunluk")


ClickHouse tanılama yaklaşımı sorgu log'ları, sistem tabloları, profil sayaçları ve gerektiğinde bellek/CPU örnekleme verilerinin birlikte yorumlanmasına dayanır. `system.query_log` tamamlanmış sorguların süre, okunan satır, bellek ve bazı hata bilgilerini sağlayabilir; fakat hangi alanların yazıldığı ve log'un etkinliği yapılandırmaya bağlıdır. Üretimde gözlem bileşeni eklenmesi kendi kaynak ve güvenlik maliyetini doğurur.

Sorgu gecikmesi artışı görüldüğünde doğrudan bellek limiti yükseltmek veya thread sayısını artırmak sistematik teşhis değildir. Önce değişen etken sınıflandırılır: veri hacmi, şema, sıralama anahtarı, sorgu pattern, birleştirme baskısı, disk doluluğu, önbellek, network ve connector. `system.query_log` sonuçlarından okunan satır, okunan byte ve sorgu duration eğilimleri alınabilir. `system.parts` veri parçası birikimi, `system.merges` arka plan yükü ve bellek profili ayrı sinyaller sağlar. Profiler çıktıları sampled olduğu için deterministik call-count bilgisi olarak yorumlanmamalıdır. Üretim sorgusu hassas değerler içeriyorsa profiling/logging erişim politikasıyla uyumlu olmalıdır. Performans regresyonu, kontrollü geri alma ve tekrarlı test olmadan tek ölçümle açıklanamaz.

### 30.1. System.query_log, Veri Parçaları, Merges, Metrics Tabloları

`system.query_log` tamamlanan ve başarısız sorguların yürütme ölçülerini, `system.parts` fiziksel veri parçalarını, `system.merges` ve `system.mutations` arka plan işlemlerini, `system.metrics` anlık sayaç/göstergeleri, `system.events` kümülatif olayları görünür kılar. Günlük tablolarının etkinliği ve saklama ayarları yapılandırmaya bağlıdır. `SYSTEM FLUSH LOGS`, toplu yazılan günlük kayıtlarının görünür olmasını hızlandırabilir; her sorguda uygulanması ölçüm yükünü değiştirebilir.

```sql
SELECT
    event_time,
    query_id,
    query_duration_ms,
    read_rows,
    read_bytes,
    memory_usage
FROM system.query_log
WHERE type = 'QueryFinish'
  AND event_time >= now() - INTERVAL 1 HOUR
ORDER BY query_duration_ms DESC
LIMIT 20;
```

Bu örnekte SQL metni bilerek gösterilmiyor: `query` alanı kullanıcı tanımlayıcıları, değişken değerleri veya yanlış yapılandırılmış gizli bilgileri içerebilir. Günlük tablosu yetkileri de hassas veri erişim sınırının parçasıdır.

`query_duration_ms` sunucu tarafının süre ölçüsüdür; istemcideki bağlantı kurulumu, ağ gecikmesi ve sonuç tüketme süresiyle aynı metrik değildir. Dağıtık sorguda yerel sistem tabloları düğümlerin ölçülerini kendiliğinden tek kayda dönüştürmez; istemci sorgusu ile alt sorgular `query_id` ve `initial_query_id` üzerinden ilişkilendirilerek incelenir. Okunan satır/bayt, bellek ve `ProfileEvents` değerleri CPU, G/Ç veya kuyruk darboğazı hipotezini sınamak için birlikte değerlendirilir. Örneklemeli profiler veya zorla günlük flush uygulaması yüksek trafikli sistemde ölçülen işi etkileyebileceğinden tanılama maliyeti ayrıca gözetilir. [16, 45]

26.8 ve sonraki sürümlerde `system.user_query_log`, mevcut kullanıcının sorgu geçmişini bütün kullanıcıların `system.query_log` kayıtlarını açmadan inceleme imkanı sağlar. Uzun süren bir arka plan sorgusu için `query_id` biliniyorsa işlem aktifken `system.processes`, tamamlandıktan sonra ilgili sorgu günlüğü incelenir. Sorgu günlüğünün asenkron diske yazılması nedeniyle kaydın anlık olarak bulunamaması işin başarısız olduğu anlamına gelmez. Süre, okunan satır sayısı, hedefte oluşan veri ve hata kodu birlikte değerlendirilmelidir. [46]

### 30.2. Sorgu Profilleme, Örneklemeli Yığınlar ve Alev Grafikleri

Örneklemeli CPU profiler, yürütme sırasında alınan thread stack örneklerinin dağılımıyla hangi kod yollarının işlemci zamanı tükettiğini tahmin eder. Flame graph'da bir fonksiyonun genişliği, örneklem kümesindeki toplam ağırlığı temsil eder; fonksiyonun tek başına darboğaz yarattığını kanıtlamaz. Bloklayıcı disk beklemesi, kilit beklemesi ve CPU yürütmesi aynı örnekleme tekniğiyle eşit görünürlükte ölçülmeyebilir.

Örnekleme olasılığı düşük ve işlem süresi kısa bir sorguda profil istatistikleri yüksek varyans gösterebilir. Kısa sorgular için toplam profil süresi ve `system.query_log` değerleri; uzun CPU-ağırlıklı sorgular için örneklenmiş yığınlar birlikte değerlendirilmelidir. Profiling açıkken oluşan ek CPU ve bellek maliyeti de ölçüm sonucunu değiştirebildiği için deney öncesi ve sonrasında aynı sorgu kümesi çalıştırılır.

Özellikle JOIN ve toplulaştırma darboğazlarında yalnız flame graph'a dayanarak indeks eklemek hatalı olabilir. Önce `EXPLAIN`, okunan satır sayısı ve bellek kullanımı incelenir; düşük seviyeli profil ancak hangi işlemci veya bellek işleminin baskın kaldığını göstermek için kullanılır.

### 30.3. Jemalloc Bellek Tahsisi Profilleme ve Yığın Belleği İncelemesi

jemalloc allocation profiling bellek tahsis yerlerini açığa çıkarabilir. Heap anlık görüntü toplam resident belleği birebir açıklamayabilir; allocator fragmentation, mmap ve sayfa önbelleği ayrı kalemlerdir. Profiling yalnız kontrollü test veya gerekli işletim döneminde kullanılmalıdır.

Jemalloc profil verisi tahsis örüntülerinin nerede yoğunlaştığını bulmaya yardım edebilir; fakat allocation miktarı ile RAM'de tutulan canlı veri miktarı aynı değildir. Heap fragmentasyonu, thread önbellek ve allocator arena davranışları RSS'yi etkiler. Bellek tanılaması sırasında profiler'ın kendisinin ek maliyet yarattığı da hesaba katılır. Sorgu aşamalarından hangisinin allocation ürettiği, tek başına toplam heap boyutundan daha değerli bir teşhis olabilir.

### 30.4. Sorgu Günlükleri, HTTP Metrikleri ve Prometheus Dışa Aktarımı

`system.query_log`, tamamlanan veya hata ile sonlanan sorguların yürütme süresini, okunan/verilen veri miktarını ve bellek kullanımını incelemek için kullanılabilir. Bu günlük düğüm bazlıdır; replikalı kurulumda tek sunucudan yapılan sorgu kümenin tamamını göstermeyebilir. `system.metrics` anlık sayaçlar, `system.events` birikimli sayaçlar ve `system.part_log` veri parçası yaşam döngüsü olayları sunar. Bunların saklama biçimi ve kullanılabilirliği sunucu yapılandırmasına bağlıdır.

```sql
SELECT event_time, query_id, query_duration_ms,
       read_rows, read_bytes, memory_usage
FROM system.query_log
WHERE type = 'QueryFinish'
  AND event_time >= now() - INTERVAL 1 HOUR
ORDER BY query_duration_ms DESC
LIMIT 20;
```

SQL metni kullanıcı girdileri veya hassas literal değerler içerebilir; günlük tablosuna erişim, saklama süresi ve olası maskeleme gereksinimleri tanımlanmalıdır. Prometheus biçiminde dışa aktarılan metriklerin her SQL çağrısının tam izini tuttuğu varsayılmamalıdır. Üç tür kanıt ayrı ilişkilendirilir: zaman serisi sayaçları kaynak doygunluğunu; sorgu log belirli sorgu örüntüsünü; veri parçası/birleştirme günlükleri arka plan depolama işini gösterir. Sayıların karşılaştırılabilmesi için saatler, sorgu kimlikleri ve düğüm adları eşleştirilir.

### 30.5. OOM İzleme, Bellek Aşımı ve Bellek Sızıntısı Tanısı

OOM canary bellek basıncı için uyarı/koruma aracı olabilir; bellek sınırı aşımı sırasında işlenen sorgunun sonlandırılması tasarıma bağlıdır. Kernel OOM kayıtları, sorgu zirve belleği ve birleştirme tahsisleri aynı zaman çizgisinde incelenir. OOM her zaman memory leak değildir.

OOM canary ve bellek baskısı mekanizmaları bütün süreçlerin çökmesini azaltmayı hedefleyebilir; hata sonrası sorgu iptali veri kaynağındaki işlemin otomatik geri alındığı anlamına gelmez. Bellek sızıntısıyla zaman içinde büyüyen önbellek veya allocator rezervasyonu ayrıştırılmalıdır. RSS, sorgu memory metrics ve heap profile birlikte okunur. Aynı anda çalışan INSERT, birleştirme ve SELECT yükleri birbirini etkileyebileceği için tanılama kontrollü eşzamanlılık koşullarıyla yapılmalıdır.

### 30.6. Arka Plan Birleştirme ve Değişiklik İşlemlerinin İzlenmesi

Birleştirme kuyruğunun büyümesi küçük INSERT veri parçalarını, disk doygunluğu veya ağır mutation'larla ilişkili olabilir. `system.merges`, `system.mutations`, `system.parts` ve `system.part_log` ölçümleri olayın türüne göre birleştirilir. Birleşmelerin çok sürmesi tek başına hata değildir; bekleyen parça sayısı ve veri alım hızının trendi önemlidir. Background işlere ayrılan CPU/disk kaynaklarını aşırı artırmak ön plandaki analitik sorguların p99 gecikmesini kötüleştirebilir.

Veri parçası üretim hızı λₚ ve birleştirmeyle kaldırılan net veri parçası hızı μₚ olarak tanımlanırsa uzun süre λₚ > μₚ olması etkin veri parçası sayısını büyütür. Bu bir kuyruk kararlılığı problemidir; yalnız anlık `system.merges` satır sayısına bakmak nedeni teşhis etmez. Veri parçası üretimi veri alımındaki küçük batch'lerden mi yoksa yüksek bölüm kardinalitesinden mi kaynaklanıyor sorusu ayrı ölçülür.

Birleşmelerin tamamlanma süreleri çok geniş dağılıyorsa ortalama süre tek başına yeterli değildir. En eski bekleyen veri parçası, disk I/O doygunluk, birleştirme işlem hacmi ve başarısız mutation kayıtları aynı zaman ekseninde karşılaştırılır. `OPTIMIZE TABLE ... FINAL` tekrar tekrar çağrılarak kalıcı kapasite yetersizliği gizlenmemelidir.

### 30.7. Sorgu İşlem Hacmi, Gecikme Dağılımları ve Kaynak Doygunluğu

İşlem hacmi arttıkça doygunluk noktasında kuyruğun büyümesi ve p99 gecikmesinin sıçraması olasıdır. Toplam QPS tek başına kullanıcı deneyimini yansıtmaz; concurrency, hata oranı ve veri tazeliği de incelenir. Aynı sistem farklı sorgu karışımlarında farklı kapasiteye sahiptir.

Kuyruk büyümesi, hizmet hızı ve gecikme dağılımlarının matematiksel modeli [Kuyruk Teorisi ve Stokastik Süreçler](/kuyruk-teorisi-ve-stokastik-surecler) dersinde açıklanır.

Kuyruk teorisinde Little yasası uygun durağan koşullarda `L=λW` eşitliğiyle ortalama sistemdeki iş sayısı `L`, birim zamandaki tamamlanma hızı `λ` ve ortalama yanıt süresi `W` arasındaki ilişkiyi verir. Bu eşitlik ClickHouse'un kaynak doygunluğunda neden daha yüksek concurrency'nin her zaman işlem hacmi sağlamadığını açıklar. CPU veya disk sabit bir kapasiteye ulaştığında geliş hızının artırılması bekleyen sorgu sayısını ve p99 gecikmesini büyütebilir.

Örneğin saniyede 100 sorgu tamamlanan sistemde ortalama yanıt süresi 200 ms ise Little yasası yaklaşık 20 aktif/bekleyen sorguya işaret eder. Aynı işlem hacmi altında yanıt süresi 2 saniyeye çıktığında ortalama sistem yükü 200'e yükselir. Bu değerler sınanmış gözlem değil denklem örneğidir. Sorgu queue, background merges ve Kafka veri alımı aynı sunucuda yarışıyorsa yalnız sorgu işlemcisinin CPU grafiği üzerinden darboğaz teşhisi yapmak yetersizdir.

### 30.8. Performans Gerilemesi ve Hizmet Düzeyi Hedefleri

Performans gerilemesi testinde veri hacmi, sorgu mix, sürüm, önbellek, `max_threads`, disk ve parallel replica davranışları sabitlenir. SLO yalnız ortalama sorgu süresi değildir; zaman penceresindeki başarı, gecikme ve veri doğruluğu gereksinimlerini içerir.

Performans regresyonu tek bir sorgunun önceki haftadan yavaş çalışmasıyla sınırlı değildir. Aynı veri hacmi, önbellek durumu, eşzamanlılık ve sorgu planı koşullarında p95/p99 değişimi incelenir. Artan veri hacmi nedeniyle sürenin yükselmesi ürün sürümü regresyonundan ayrılmalıdır. Service düzey objective, sorgu sınıfı bazında gecikme, kullanılabilirlik ve sonuç tazeliğini ayrı tanımlayabilir; başarısız sorguların istatistiğe dahil edilme kuralı açık olmalıdır.

## Ünite 31: ClickHouse Yönetim ve Geliştirme Araçları

ClickHouse komut satırı araçları üretim sunucusunun dışında sorgu biçimlendirme, yerel dosya analizi, başarım karşılaştırması ve yedek inceleme gibi farklı işler yapar. Uygun araç seçimi, sunucu üzerinde gereksiz veri akışını önleyebilir; fakat bir aracın desteklenmesi veri güvenliği ve erişim sınırlarını ortadan kaldırmaz.

ClickHouse araçlarının ayrılması operasyon süreçlerini sadeleştirir: yerel Parquet dosyasını analiz etmek için dağıtık küme kurulması gerekmez, `clickhouse-local` yeterli olabilir. `clickhouse-benchmark` aynı sorgu pattern'i tekrar ederek karşılaştırma yapabilir; fakat test datasının gerçek sıkıştırma ve eşzamanlılık profilini taşımaması sonucu genellenemez kılar. `clickhouse-format` biçimi değiştirir, SQL'in doğru ve güvenli olduğunu kanıtlamaz. Keeper veya disk yönetimi yapan araçlar veri ve koordinasyon durumunu doğrudan etkileyebileceğinden erişim kısıtları gerekir. Obfuscation veri gizliliği testinde yararlı olabilir ama kişisel verinin geri döndürülemez anonimleştirilmesiyle aynı şey değildir. CLI exit status ve örnek çıktı uygulama otomasyonunda denetlenmelidir.

### 31.1. ClickHouse-local ile Sunucusuz SQL

`clickhouse-local` sunucu oluşturmadan dosya formatlarını SQL ile işleyebilir; Parquet veya CSV üzerinde tek düğümlü analiz için uygundur. Kalıcı dağıtık tablo semantiği beklenmemelidir. Bellek ve disk sınırları aynı makineye aittir.

Yerel dosyanın SQL ile analiz edilmesi:

```bash
clickhouse local --query "SELECT count() FROM file('events.parquet', Parquet)"
```

Dosya konumu çalışma dizinine ve erişim izinlerine bağlıdır. Sunucusuz çalışması sınırsız bellek veya disk kullanımı anlamına gelmez.

`clickhouse-local`, Parquet, CSV veya diğer yerel kaynakları analiz etmek için sürekli çalışan ClickHouse sunucusu gerektirmeyebilir. Bu kullanım yüksek hacimli dosyalarda veri tipi denemesi, dönüşüm ve başarım karşılaştırması için yararlıdır. Ancak tek süreç üzerinde hızlı çalışan sorgu, dağıtık kümede ağ ve replica maliyetini temsil etmez. Üretilen şemanın kalıcı sunucuda kullanılacak motor ve sıralama anahtarıyla uyumlu olduğu ayrıca denetlenmelidir.

### 31.2. ClickHouse Başarım Karşılaştırması ve Deney Otomasyonu

`clickhouse-benchmark` aynı sorguyu belirli sayıda veya eşzamanlılıkta çalıştırmaya yardımcı olabilir. Yalnız bu aracın çıktısı tam üretim performansı değildir; veri ve çevresel koşullar ayrıca kaydedilmelidir. Önbellek ısınması ve istemci bağlantı tekrar kullanımı sonucu etkiler.

`clickhouse-benchmark` istemci üzerinden sorgu tekrarı ve eşzamanlılık deneylerine yardımcı olur. Ölçüm çalıştırılmadan önce başarım karşılaştırması SQL'inin doğru sonuç döndürdüğü ve veri kümesinin sabit olduğu doğrulanmalıdır. İstemci ile sunucunun aynı makinada olması ağ giderlerini azaltır; gerçek API tüketici gecikmesini modellemeyebilir. Yük testi bitmeden çalışan background merges, veri alımı ve diğer sorguların kaynak paylaşımı bilinmelidir.

Sorguları rastgele sırada çalıştırmak, ilk sorgunun disk önbelleğini ısıtıp diğerine avantaj sağlaması riskini azaltır. Bir ısınma aşaması raporlanabilir, fakat ısınma çalıştırılmış sonuçlarla soğuk önbellekle elde edilen sonuçlar aynı dağılımda birleştirilmez. Başarım karşılaştırması örnekleri yeterli sayıda tekrarlanmalı; kararsız ölçümler tek bir medyan değere indirgenmeden dağılımlarıyla verilmelidir.

### 31.3. ClickHouse-format, Compressor ve Obfuscator

`clickhouse-format` SQL biçimlendirme; compressor kodlama testleri; obfuscator hassas veriye benzemeyen örnek oluşturma gibi kullanım alanları taşır. Obfuscation yöntemlerinin gerçek anonimleştirme ve yeniden tanımlanamama garantisi verdiği varsayılmamalıdır.

Biçimlendirme aracı SQL'in anlamını değiştirmeden yazımını tekilleştirmek için kullanılır; biçimlendirilmiş bir ifadenin sunucuya karşı çalışacağının tek başına kanıtı değildir. Sıkıştırma aracının değerlendirdiği veri örneğinin dağılımı, üretim sütununun dağılımıyla eşdeğer değilse oranlar taşınamaz. Gizleme aracının ürettiği çıktı yalnızca gizleme tekniğinin kapsamı içinde değerlendirilebilir; yeniden tanımlama ve veri sızıntısı riski ayrıca sınanır.

`clickhouse-format` ile biçimlenen SQL'in yürütme semantiği sunucudaki SQL analyzer sürümüne ve kullanılan fonksiyonlara bağlıdır. Biçimleyici ile sunucu arasında sürüm farkı varsa sözdizimin yalnız bir tarafta tanınıyor olması mümkündür. Otomatik biçimlendirme, sorguyu gerçek tablo şeması üzerinde `EXPLAIN` ile doğrulamanın yerini tutmaz.

Obfuscation, gerçek kişilere ait olay verisini bilimsel deney için otomatik olarak anonimleştirmez. İstisnai alan değerleri, cihaz parmak izleri, düşük frekanslı olay birleşimleri ve zaman damgaları yeniden tanımlamaya izin verebilir. Paylaşılan test verisinin istatistiksel özelliklerini korumak ile tersine eşleştirmeyi engellemek iki ayrı doğrulama hedefidir.

### 31.4. ClickHouse-disks ve Dosya Sistemi İncelemesi

`clickhouse-disks`, ClickHouse tarafından tanımlanmış disk soyutlamaları üzerinde dosya inceleme ve bakım işlemleri için kullanılır. Yerel dosya sistemiyle aynı şey değildir: bir “disk” yapılandırması uzak nesne depolamaya, katmanlı saklamaya veya önbelleğe dayanabilir. Bu yüzden dosyanın işletim sistemi yolundaki görünürlüğü ile veri parçasının sunucu tarafından etkin kabul edilmesi farklı koşullardır.

Bir veri parçası yalnız sıkıştırılmış sütun baytlarından oluşmaz; işaret dosyaları, birincil indeks, denetim toplamları ve üstveri da içerir. Bir veri parçası klasörünün elle silinmesi veya başka tabloya taşınması, ClickHouse'un parça kayıtları ve replikasyon görevleriyle çelişebilir. Doğrulama için `system.disks`, `system.storage_policies` ve `system.parts` birlikte kullanılabilir; bütün sistem tablolarının her dağıtımda aynı alanlara sahip olduğu varsayılmamalıdır.

Depolama kullanımını değerlendirirken `bytes_on_disk` ile uzak nesne deposunun faturaladığı baytlar birebir eşit olmayabilir. Paylaşılan nesne referansları, üstveri, saklama sürümleri ve yerel önbellek maliyetleri fark oluşturur. Fiziksel bakım gerekliyse sunucunun desteklediği DDL ve yedekleme işlemleri izlenmelidir.

### 31.5. ClickHouse-keeper-client ve HTTP API

Keeper istemcisi ve HTTP API dağıtık koordinasyon üstverisini kontrol etmeyi sağlar. Keeper yollarına gelişi güzel müdahale replika sağlığını etkileyebilir. Araç yetkisi yalnız yönetici kapsamına verilmelidir.

`clickhouse-keeper-client` Keeper koordinasyon düğümündeki üstveri ve oturum durumlarının incelenmesinde kullanılabilir. Keeper, ClickHouse sorgu verilerini saklayan genel amaçlı bir uygulama veritabanı değildir; replikasyon koordinasyonuna yönelik tutarlılık görevleri üstlenir. HTTP API kullanılabiliyorsa bu arayüz yönetim erişimi olarak ele alınır. Koordinasyon üstverisini rastgele değiştirmek replikasyon görevlerini ve düğüm tutarlılığını bozabilir.

Keeper'a bağlı istemcinin okuma yetkisi ile değiştirme yetkisi ayrılmalıdır. Belirli replica üstverisi yanlışlıkla kaldırılırsa ClickHouse düğümünün fiziksel veri parçalarını sağlam olsa bile koordinasyon süreci bozulabilir. Üretimde Keeper işlemleri yalnız izleme amacına göre açılan kısıtlı hesaplarla sınırlandırılmalıdır.

### 31.6. ODBC Köprüsü, Backupview ve Statik Dosya Yükleyici

ODBC bridge dış veri kaynaklarıyla bağlantıda köprü olabilir; backupview arşiv incelemesinde kullanılır. Static-file disk uploader belirli uzak depolama senaryolarıyla ilgilidir. Her aracın ağ/secret ve veri erişim izleri değerlendirilir.

ODBC bridge uygulamaları, ClickHouse sorgu sürecinden ayrı bir dış veri kaynağına erişim katmanı sağlayabilir. Backup view ve static-file yükleme araçları farklı dosya/nesne erişim işlemlerine ilişkindir; bütün dağıtımlarda varsayılan biçimde kurulu oldukları varsayılmamalıdır. Bu araçlar kullanılacaksa çalıştıkları kullanıcı hesabı, sır yönetimi ve dosya sistemi erişim yetkileri ayrıca incelenmelidir.

Bu yardımcı bileşenler ürünün ana SQL işlemiyle aynı güvenlik alanında kabul edilmemelidir. Bağlandıkları uzak kaynağın kimlik bilgileri, dosya yükleme izinleri ve ağ yönlendirmesi ayrı ele alınmalıdır. Kritik bir aktarım hatasında yeniden deneme işleminin aynı dosyayı iki defa üretip üretmediği de doğrulanmalıdır.

### 31.7. Clickhousectl ve İstemci Geliştirme

`clickhousectl` adıyla sunulan üçüncü taraf yönetim araçları, ClickHouse'un kendi `clickhouse-client` ikilisiyle aynı sürüm ve destek sözleşmesine sahip değildir. Sunucu üzerinde çalışan komutların etkisi, istemcinin arayüzünden çok gönderilen SQL, yetki ve sunucu sürümüne bağlıdır. Yönetim otomasyonunda kullanılan dış araç bakım durumu, proje kaynağı ve sürüm uyumluluğu doğrulanmalıdır.

Bir CLI işleminde çıkış kodunun sıfır olması, hedef iş kuralının tamamlandığını tek başına kanıtlamaz. Örneğin veri alımı tamponlanmışsa sunucunun kalıcılaştırma onayı; yedekleme başlatılmışsa işlem durumunun tamamlanması; dağıtık DDL yürütülmüşse bütün hedef düğümlerin sonucu kontrol edilmelidir. Otomasyon için zaman aşımı, yeniden deneme politikası, sorgu kimliği ve son durum sorgulaması birbirinden bağımsız tanımlanır. `INSERT` yeniden denemelerinde mükerrer kayıt riskini değerlendirmeden körlemesine yeniden deneme uygulanmaz.

### 31.8. Komut Satırı ve Web Arayüzü Davranışları

Web UI gösterimi istemci tarafında filtre ve sonuç sınırlaması uygulayabilir; CLI doğrudan daha geniş çıktı üretebilir. Karşılaştırma sorgunun gerçek SQL'ini ve server-side `LIMIT` kullanımını temel alır. Görsel tablo görünümündeki satır sayısı toplam sorgu sonucu değildir.

SQL Console ve CLI'da varsayılan çıktı biçimi, oturum ayarları ve sorgu timeout'ları farklı olabilir. Etkileşimli arayüzün tabloya otomatik LIMIT uygulaması veya sonuçları bellekte göstermesi, sunucuda aynı SQL'in farklı davranışta olduğu izlenimi yaratabilir. Gerçek benchmark'ta sunucu tarafı sorgu id ve `system.query_log` değerleri kullanılmalı; istemci yanıtı tüketme süresi ayrıca raporlanmalıdır.

Resmi ClickHouse araç ekosistemindeki `chdig`, canlı sorguların ve sunucu bileşenlerinin terminal üzerinden incelenmesi için bir TUI sağlar. 26.10 sürüm sunumunda Keeper tarayıcısı ve düğüm başına özet gibi işlevler açıklanmıştır. Terminal aracıyla sunucunun gerçek veri erişim yetkileri aynı şey değildir; araç bağlantı kurduğu hesabın erişim sınırlarına tabidir. Web arayüzü, notebook veya terminalde görülen bir plan, sunucuda ölçülen `read_bytes`, bellek ve sorgu süresiyle doğrulanmadıkça performans sonucunu kanıtlamaz. [41]

## Ünite 32: ClickHouse ve Diğer Analitik Veri Tabanı Sistemleri

Analitik sistemler aynı veri hacminde birbirinden farklı yük türlerini hedefler. ClickHouse genel amaçlı sütun yönelimli yüksek hızlı analitik, Apache Druid ve Pinot gerçek zamanlı olay sorgulaması, DuckDB gömülü analitik, veri ambarı bulut servisleri ayrık kaynak yönetimi gibi tasarım ağırlıkları taşır. Elasticsearch ise esas olarak Lucene üzerinde geliştirilmiş dağıtık arama ve analitik motorudur; ClickHouse türünde ilişkisel sütun yönelimli OLAP veritabanı değildir. Bununla birlikte belge saklama ve vektör veritabanı yetenekleri bulunduğu için genel anlamda veri tabanı işlevi taşımadığını söylemek doğru değildir.

ClickHouse ile Elasticsearch karşılaştırması yalnız bir sorgu tipindeki gecikme oranını raporlamakla yapılamaz. Inverted index ile metin terim araması, sütun veri bloklarının sıkıştırılmış taranması ve SQL toplulaştırma farklı fiziksel algoritmalardır. Elasticsearch full-text relevancy, analyzer ve scoring gereksiniminde doğal seçenek olabilir; ClickHouse geniş numeric/temporal GROUP BY iş yükünde uygun olabilir. Apache Druid/Pinot yüksek hacimli olay analitiği, DuckDB tek süreç içinde embedded OLAP, BigQuery/Snowflake yönetilen veri ambarı deneyimi gibi farklı sistem seçimi boyutlarını gösterir. Her alternatifte ingest freshness, update modeli, sürüm, kayıp/kurtarma semantiği, JOIN davranışı ve toplam işletim maliyeti ölçülmelidir. Eşit veriye yüklenmiş fakat farklı sonuç döndüren iki sorgunun gecikmeleri kıyaslanamaz.

### 32.1. Apache Druid, Pinot, Doris ve StarRocks

Druid segment indeksleri ve akış veri alımı; Pinot düşük gecikmeli gerçek zamanlı OLAP; Doris ve StarRocks MPP SQL ve analitik servis iş yükleri ile karşılaştırılabilir. Her sistemin JOIN, ingest freshness ve sorgu eşzamanlılığı kapasitesi sürüm ve dağıtımla farklılaşır. Sadece ürün tanıtımındaki tek sorgu süresiyle hüküm verilmez.

Druid ve Pinot yüksek hacimli olay akışları ve düşük gecikmeli analitik için indeks ve segment odaklı modeller sunar. Doris ve StarRocks MPP analitik SQL ve depolama optimizasyonlarına farklı mimari yaklaşımlarla yönelir. Ürünleri tek bir OLAP kategorisinde toplamak yeterli değildir; veri güncelleme modeli, veri alımı gecikme, kaynak izolasyonu, JOIN davranışı ve operasyonel karmaşıklık karşılaştırılmalıdır. Aynı sorgu ailesi farklı sistemlerde doğal optimizasyonlar gerektirdiğinden adil deney bu optimizasyonları ve oluşturma maliyetlerini belirtir.

### 32.2. DuckDB, Vertica, Snowflake, BigQuery, Redshift

DuckDB tek süreç içinde sütun yönelimli/vectorized sorgu için güçlüdür; Vertica MPP column-store sınıfındadır. Snowflake, BigQuery ve Redshift yönetilen bulut analitik yaklaşımları sunar. Depolama ve compute ayrıştırması, maliyet modeli ve operasyon sorumluluğu sistem seçiminde belirleyicidir.

DuckDB çoğunlukla yerel süreç içinde analitik yürütme için güçlü bir seçenekken Snowflake, BigQuery ve Redshift yönetilen veri ambarı mimarileri sunar. Vertica da sütun yönelimli MPP yaklaşımıyla anılır. Karşılaştırmada sorgu iş yükü kadar çok kullanıcı eşzamanlılığı, ağ gecikmesi, ölçek büyütme süresi ve veri aktarım bedeli ele alınır. Tek makinedeki DuckDB testiyle çok düğümlü bulut veri ambarı testini yalnız milisaniye sonucuyla karşılaştırmak mimari açıdan eksiktir.

chDB ile DuckDB'nin karşılaştırılması, sunucusuz/işlem içi analitik motorlar düzeyinde yapılmalıdır. chDB, ClickHouse çekirdeğini Python sürecinde çalıştırır; dosya, DataFrame ve benzeri kaynakları SQL ile sorgulayabilir. Bu model, ağ üzerinden hizmet veren ClickHouse Server veya bulut kümesinin operasyonel sorumluluklarıyla aynı değildir. DuckDB ve chDB için Parquet dosya taraması, DataFrame dönüşümü ve sonuç aktarımında kullanılan bellek kopyaları ayrı ölçülür. Tek süreçli bir deneyi dağıtık replikasyon, sürekli veri alımı veya çok kullanıcılı sorgu izolasyonu karşılaştırması gibi yorumlamak metodolojik olarak yanlıştır. [47]

### 32.3. Oracle/PostgreSQL/MySQL Analitik Uzantıları

Oracle, PostgreSQL, MySQL analitik sorgu yürütebilir; doğru indeks, bölüm ve parallel sorgu özellikleri vardır. Ancak OLTP ile aynı kaynak bütçesini paylaşan ağır taramaların p99 ve I/O davranışı kritik olabilir. PostgreSQL extension'ları veya Oracle Exadata özellikleri karşılaştırmada ayrıca tanımlanmalıdır.

Oracle, PostgreSQL ve MySQL yalnızca işlemsel sorgu çalıştıran ürünler değildir; analitik sorgular, paralel yürütme, indeksleme, partitioning veya ek uzantılar yoluyla geniş raporlama yüklerini karşılayabilir. ClickHouse tercihinin dayanağı işlemsel motorların analitiği yapamaması değil, belirli sorgu dağılımında kaynak ve maliyet etkinliğinin daha iyi olabilmesidir. Geçiş kararı, kaynak sistem üzerindeki yükü azaltırken CDC ve çift veri saklama maliyetini artırabileceği için toplam etkiyle değerlendirilir.



PostgreSQL üzerindeki uygulamaların bir bölümünde analitik sorgu ClickHouse'a taşınırken uygulamanın bütün veri erişim katmanını değiştirmek gerekmez. ClickHouse'un 2025 sonunda duyurduğu `pg_clickhouse` uzantısı, belirli sorguları PostgreSQL arayüzünden ClickHouse'a iletmeye yönelik bir entegrasyon modelidir. Uzantı, analitik iş yükünü kaynak PostgreSQL işlem motorunun üzerinde çalıştırmanın eşdeğeri değildir; pushdown edilebilen ve edilemeyen operatörler, yetki eşlemesi, veri tazeliği ve hata sınırları ayrıştırılmalıdır.

Bu seçenek yalnız Oracle veya PostgreSQL'den CDC ile sürekli veri kopyalamayı değil, istemcilerin kullandığı sorgu erişim yolunu da değiştirebilir. Gömülü extension ile fiziksel veri aktarımı ayrı mimari kararlardır; bunların gecikme ve doğruluk etkileri birbirine karıştırılmamalıdır. Kaynak: https://clickhouse.com/blog/pg_clickhouse-fastest-analytics-for-postgres
### 32.4. Elasticsearch ve Lucene: Ters İndeks ile Belge Depolama

Elasticsearch ters indeksle terimden belge kimliklerine erişimi optimize eder, Lucene doc values bazı sütun yönelimli aggregations için kullanılabilir. Belge araması, relevancy scoring ve metin çözümlemesi ClickHouse'un temel sütun tarama yaklaşımından ayrılır. Elasticsearch doküman modelinde güncelleme çoğu kez yeniden indeksleme maliyeti taşır.

İki farklı sorgu sınıfı düşünülür: “içerisinde `timeout` sözcüğü geçen ve kök biçimi eşleşen mesajları relevance sırasıyla getir” ile “son 30 gündeki servis başına 99. yüzdelik gecikmeyi hesapla”. Birincisi Lucene tabanlı inverted index ve metin analizinin doğal iş yüküdür; ikincisi sıkıştırılmış numeric kolonlar ve agregasyonun doğal iş yüküdür. Elasticsearch doc values üzerinden analytics de yapabilir; ClickHouse metin indeksleme de sunar. Soru motorların tek bir işlemi yapıp yapamaması değil, çok sayıda sorgu altında hangi fiziksel mimarinin sürdürülebilir avantaj sağladığıdır.

Elasticsearch, Apache Lucene tabanlı dağıtık arama ve analitik motorudur. İlişkisel OLTP veritabanı veya ClickHouse gibi sütun yönelimli OLAP DBMS değildir; buna rağmen belge saklama, sorgulama ve vektör arama özellikleri nedeniyle geniş anlamda veritabanı işlevleri taşır. Lucene inverted index terimden belge listesine erişimi hızlandırır; `doc_values` ise bazı alanların sütun benzeri analitik erişimine hizmet eder. Bu iki yapı aynı veri kümesinde farklı maliyetlerle bir arada bulunabilir.

ClickHouse 26.2 ile birlikte yerel full-text inverted index kabiliyeti resmi olarak genel kullanıma açılmıştır. Bu, metin arama ile OLAP aggregation'ı aynı motor üzerinde birleştirmeyi kolaylaştırır; fuzzy relevance, karmaşık metin analizörleri, belge skorlama ve arama ürünlerinin bütün davranışlarının otomatik olarak aynı olduğu sonucu çıkarılamaz. Sistem karşılaştırmasında yalnız count/gruplama değil metin normalizasyonu, tokenizer, phrase search, relevance scoring, update sıklığı ve index building maliyeti de değerlendirilmelidir.

ClickHouse tarafından yayımlanan 2026 OpenTelemetry karşılaştırması farklı veri büyüklükleri, soğuk/sıcak önbellek durumları ve tam metin sorgu ailelerini ayrı ölçer: https://clickhouse.com/blog/elasticsearch-log-analytics-clickhouse.

26.10'un deneysel Elasticsearch motoru, Elasticsearch 7.12 veya üzerindeki indekslerin point-in-time tabanlı sayfalama ile ClickHouse içinden okunmasına olanak tanır. Motorun okuma odaklı olması, veri kaynaklarındaki güncelleme ve silme semantiğini ortadan kaldırmaz; arama indeksinin güncelliği ile ClickHouse'un kendi MergeTree depolaması birbirinden ayrıdır. Belge içerikleri JSON olarak ele alınabilir; sorgu bir kısmı Elasticsearch tarafına aktarılıyorsa iki motorun filtreleme ve sıralama davranışlarının eşdeğerliği doğrulanmalıdır. Bu bütünleşme, Elasticsearch'ün OLTP ilişkisel veritabanı olduğu anlamına gelmez. [41]

### 32.5. Tam Metin Arama ile Sütun Yönelimli OLAP Ayrımı

Tam metin arama eşleşme ve relevance sıralaması; OLAP büyük hacimli numeric/grouped toplulaştırma iş yüküdür. ClickHouse'un metin indekslerinin bulunması iki motorun tüm arama özelliklerinin eşit olduğu anlamına gelmez. Arama ve agregasyonun birlikte yoğun olduğu iş yükünde hibrit mimari gerekebilir.

Elasticsearch'ün inverted index yapısı terimden belgelere erişim, sözcük analizörü ve relevance scoring gibi gereksinimlerde belirleyicidir. ClickHouse sütunlu depolama, agregasyon ve büyük taramalarda farklı optimizasyon sunar; güncel tam metin arama özellikleri iki sistem arasındaki sınırı bütünüyle kaldırmaz. Belirli log sorgusunda hangi alanların full-text index'e gireceği, ne kadar indeks alanı tüketileceği ve `GROUP BY` sorgusunun nasıl çalışacağı ayrı ölçülmelidir. Arama motoru ile OLAP DBMS aynı sınıflandırma değildir.

ClickHouse'un 2026 tam metin arama işlevleri, sütunlu analitik yürütme hattına ters indeks üzerinden gelen eşleşmelerin katılmasını sağlar. Bu mimari log analitiğinde arama sonrası `GROUP BY` ve zaman penceresi sorgularını aynı veri tabanında birleştirebilir. Ancak Elasticsearch'ün analizörleri, relevance scoring, esnek eşleşme ve bazı arama özellikleriyle birebir işlev eşdeğerliği ancak sorgu örneği bazında değerlendirilir.

ClickHouse tarafından yayımlanan 23 Nisan 2026 tarihli OpenTelemetry benchmark'ında 1 milyar log için disk alanı ClickHouse'ta 49,49 GiB, Elasticsearch'te 245,06 GiB; 50 milyar log için sırasıyla 2,43 TiB ve 12,01 TiB olarak verilmiştir. Bu yaklaşık beş kat depolama farkı araştırmada kullanılan eşleşen veri kümesi ve indeks yapılandırması içindir. Aynı yayında test edilen tam metin + analitik iş yükünde yaklaşık 2–6 kat sorgu avantajı bildirilmiştir. Bu veriler Elasticsearch'ün bütün arama türlerinde yavaş olduğu anlamına gelmez. Kaynak: https://clickhouse.com/blog/elasticsearch-log-analytics-clickhouse

ClickHouse'ta tam metin indeksi, vektör benzerliği ve sayısal OLAP agregasyonu birbirinden ayrı sorgu sınıflarıdır. Terim veya sözcük eşleştirmesinde ters indeks/tokenizer, semantik benzerlikte gömme vektörleri ile HNSW ve benzeri ANN yapıları, istatistiksel toplamada ise sıralı sütun blokları ve agregasyon yürütmesi kullanılır. Elasticsearch ile karşılaştırmada sorgu sınıfı eşleştirilmeden yalnız bir ürünün “arama”, diğerinin “veritabanı” olduğu söylenemez: Elasticsearch dağıtık arama ve analitik motoru olmakla birlikte belge saklama ve vektör arama özellikleri de sunar. Bununla birlikte klasik ilişkisel OLTP ve ClickHouse'un MergeTree tabanlı sütun yönelimli OLAP veri modeliyle aynı değildir. [19, 28, 48]

### 32.6. Güvenilirlik, Eşzamanlılık, Veri Alımı ve Sorgu Profili

Sistem seçiminde replica consistency, ingest-to-sorgu gecikmesi, sorgu concurrency, şema evolution, JOIN karmaşıklığı, donanım maliyeti ve 운영 yükü birlikte hesaplanır. Ürünlerin varsayılan önbellek, paralellik ve indeks politikaları aynı değilse tek tabloya dayalı başarım karşılaştırması yanıltır.

Bir analitik sistemin tek sorguda hızlı olması, çok kullanıcı altında sürekli veri alırken aynı gecikmeyi koruduğu anlamına gelmez. Aynı anda INSERT, birleştirme, replika senkronizasyonu ve 100 sorgu gibi bir üretim profili gerçekçi sonuç verir. Arıza senaryosunda eksik sonuç döndürmek ile isteği başarısız saymak ayrı kullanılabilirlik kararlarıdır. Başarım karşılaştırması performans, tazelik, doğru sonuç ve hata oranını birlikte raporlamalıdır.

### 32.7. Sistem Seçimi ve Karşılaştırma Matrisi

Karşılaştırma matrisi satırları veri hacmi, güncelleme oranı, full-text gereksinimi, analitik sorgu ailesi, kaynak izolasyonu, yedek ve destek koşullarıdır. Bir sistemin her satırda üstün olması beklenmez. Karar ölçülebilir iş yüküne bağlanır.

Sistem seçim matrisinde sorgu sınıfları, güncelleme/silme gereksinimi, sonuç tazeliği, tam metin arama niteliği, eşzamanlı kullanıcı sayısı, dağıtık kurtarma ve lisans modeli aynı ölçekte tanımlanmalıdır. Bir ürünün başka bir üründen daha yüksek sıkıştırma sağlaması, her durumda daha düşük toplam maliyet vereceği anlamına gelmez. Üretimde operatör emeği, veri akışı bileşenleri ve veri doğruluğu denetimleri de TCO'nun parçasıdır.

Karar matrisi ham skor toplamı yerine koşullu eleme ile başlayabilir. Örneğin zorunlu çok satırlı işlem ve referans bütünlüğü gereken bir modül, yalnız yüksek analitik işlem hacmi elde edildiği için ClickHouse'a taşınmamalıdır. Sonraki aşamada kalan sistemler p95/p99 sorgu gecikmesi, veri tazeliği, depolama, yönetim emeği, lisans ve kurtarma hedeflerine göre karşılaştırılır.

Farklı sistemlere aynı SQL'i çalıştırmak her zaman adil deney değildir. PostgreSQL için uygun B-tree veya sütun yönelimli eklentiler; ClickHouse için `ORDER BY`, `LowCardinality` ve uygun projection; Elasticsearch için inverted index ve doc values ayarları gereklidir. Her sistemin üretim için makul fiziksel tasarımı açıklanmalı, yapılandırma farkları raporlanmalı ve sorgu sonuçlarının semantik eşdeğerliği denetlenmelidir.

### 32.8. Karşılaştırmalı Başarım Testlerinin Genellenebilirlik Sınırları

Performans karşılaştırmalarında sorgu süresinin oranı, ölçümün bütün koşullarını temsil etmez. “1000 kat hızlı” sonucu yalnız belirli iki sürenin oranıdır; veri dağılımı, sorgu semantiği, kaynak sınırı ve eşzamanlılık değişirse sonuç da değişebilir. Karşılaştırılan sistemlerin aynı hesaplamayı yapması zorunludur: yaklaşık `uniq` ile kesin `COUNT(DISTINCT ...)` sonuçlarının doğrudan hız karşılaştırması yöntemsel olarak hatalıdır. Benzer biçimde önceden hesaplanmış özet tabloyla ham veri taraması aynı işlem maliyetini ölçmez.

İki sistemin sorgu süresi dağılımları `T₁` ve `T₂` olsun. Hızlanma `S = T₁/T₂` olarak tanımlanabilir; ancak oran hangi istatistiğin kullanıldığını belirtmelidir: medyan, p95 veya tüm sorguların toplam süresi farklı sonuç verir. Bozuk sorgular, timeout'lar ve başarısız denemeler ölçüm dışına bırakılmamalıdır. Soğuk önbellek ve sıcak önbellek koşulları ayrı raporlanır; dosya sistemi önbelleğini temizlemek tek başına CPU önbellek, işletim sistemi okuma öngörüsü ve uzak depolama önbellek etkilerini eşitlemez.

ClickHouse'un resmi PostgreSQL karşılaştırmasında yayımladığı 1000 kata kadar sorgu hızı, %50 daha az disk ve 5 kat maliyet avantajı, üretici tarafından bildirilen karşılaştırmalı değerlerdir (ClickHouse, *ClickHouse and PostgreSQL*). Bunlar Oracle, MySQL veya bütün OLAP sorguları için kanıtlanmış sabit katsayılar değildir. Akademik karşılaştırmada özgün raporun donanımı, veri kümesi, SQL metni ve ölçüm zamanı ayrıca gösterilmelidir.

## Ünite 33: Gerçek Zamanlı Analitik ve Uçtan Uca Sistem Tasarımları

İşlemsel kaynağın doğruluk sorumluluğu ile analitik tarama yükü ayrılabilir. CDC üzerinden ClickHouse kopyası üretmek, uzun analitik sorguların OLTP yolunu baskılamasını önler.

![Çift depolu gerçek zamanlı analitik animasyonu](https://alikoker.com.tr/svg/realtime-analytics-dual-store.svg "Çift depolu gerçek zamanlı analitik")


Olay ve zaman serisi analitiğinde temel veri modeli çoğu zaman append-only kayıtlardır. Bir olayın kimliği, gerçekleşme zamanı, işleme zamanı, kaynağı ve ölçü değerleri doğru seçilirse ClickHouse zaman aralığı raporlarını hızlı üretebilir. Analitik yükü Oracle'dan ayırmak OLTP kaynaklarını rahatlatabilir; ancak CDC hattındaki tazelik ve veri mutabakatı ayrıntılı yönetilir. Yüksek hacimli sistemlerde her sorgunun bütün geçmişi taraması yerine erişim örüntüsüne uygun sıralama anahtarı ve agregasyon kullanılır.

Yüksek hacimli olay verisinde her veri üreticisinin saatini doğru tuttuğu varsayılamaz. Olay zamanı geriye gidiyorsa bölüm seçimi, pencere agregasyonu ve SLA raporları etkilenir. `ingested_at` ile kaynak `event_time` farkının dağılımını saklamak veri tazeliğinin doğru analizini sağlar. Siber güvenlik olaylarında nadir ve yüksek öncelikli sinyaller, ortalama agregasyonlarda görünmez hale gelebilir; ayrıntılı olay geçmişi ve yüksek çözünürlüklü özetler birlikte tutulabilir. Çok fazla farklı etiketle metrik tutmak bellek ve indeks maliyetini artırır. Ana OLTP verisini değiştirmeden ClickHouse'a tarihsel kopya almak, kaynağın kritik işlem yolunda tam tablo taramalarını azaltabilir; CDC anlık görüntüyü ve log okumasının kaynak etkisi ölçülmelidir.

ClickHouse'un PostgreSQL karşılaştırma sayfasında **“1000× faster queries, −50% disk space, 5× cost savings”** oranları yer almaktadır. Bunlar ClickHouse tarafından yayımlanan ürün karşılaştırma iddialarıdır; aynı anda her veritabanı sürümü, her sorgu ve her donanım altında beklenen sonuçlar değildir. Aynı sayfada adı geçen müşteri anlatıları ile üretici pazarlama özetleri birbirinden ayırt edilmelidir. Kaynak: https://clickhouse.com/comparison/postgresql

ClickHouse'un 7 Mayıs 2024 tarihli Elasticsearch karşılaştırmasında PyPI veri kümesinde milyarlarca satır üzerindeki belirli sayım ve toplulaştırma sorguları incelenmiştir. Rapor edilen sonuçlar, iş yükü ve eşdeğer saklama koşullarına bağlı olarak **12–19 kat daha az depolama**, **en az 5 kat hızlı sayım/agregasyon** ve karşılaştırılabilir sorgu gecikmesi için **yaklaşık 4 kat daha ucuz donanım** yönündedir. Yayımlanan sonuçlar, `count()` ve filtreli toplulaştırma örneklerinin dışındaki bütün Elasticsearch yeteneklerini ölçmez. Kaynak: https://clickhouse.com/blog/clickhouse_vs_elasticsearch_the_billion_row_matchup

23 Nisan 2026 tarihli bir başka üretici başarım karşılaştırmasını 1, 10 ve 50 milyar satırlık OpenTelemetry log veri kümelerinde sorgu ve disk kullanımını incelemiştir. 50 milyar satır düzeyinde toplam disk alanı ClickHouse için yaklaşık **2,43 TiB**, Elasticsearch için **12,01 TiB** olarak verilmiştir; yaklaşık **5 kat** depolama farkı ve **4–6 kat** daha hızlı soğuk sorgular bildirilmiştir. Bu çalışma, 2024'teki veri kümesinden ve indeks kapsamından farklıdır; oranların birbirinin yerine geçirilmesi veya tek bir evrensel çarpan üretilmesi doğru değildir. Kaynak: https://clickhouse.com/blog/elasticsearch-log-analytics-clickhouse

### 33.1. Yüksek Hacimli Günlük ve Olay Analitiği

Uygulama log'larında timestamp, servis, severity, event_type ve uzun mesaj alanı ayrı sütunlara yerleştirilebilir. Sık sorgulanan filtrelerin sıralama anahtarı sırası, yüksek kardinaliteli mesaj metninin sıkıştırılması ve TTL birlikte tasarlanır. Tüm metni indekslemek her sorgu için gerekli değildir.

Log kayıtlarında olay zamanı ile alım zamanı ayrılmalıdır. Uygulama veya ağ cihazı yeniden bağlandığında geçmiş loglar toplu biçimde gelebilir; bunların tamamını geldiği saate yazmak olay dağılımını saptırır. Log şemasında hizmet, kaynak, seviye, izleme kimliği ve mesaj gibi alanlar farklı kardinalitelere sahiptir. Sık kullanılan filtre alanlarını typed sütun olarak saklamak ve yüksek çeşitlilikte mesaj alanlarını ayrı değerlendirmek daha kararlı performans sağlayabilir.

### 33.2. Zaman Serileri, Sürekli Toplulaştırma ve Saklama Süresi

Zaman serilerinde örnekleme aralığı, sayaç sıfırlanması, eksik veri ve geç gelen olaylar hesaplamayı etkiler. Continuous aggregate benzeri materyalleştirilmiş görünüm ile saatlik ölçüler saklanabilir; türetilen oranlar doğru pay/payda durumlarından yeniden hesaplanmalıdır. Retention ham ve özet tablolarda farklı olabilir.

Zaman serisinde her ölçümün örnekleme periyodu ve eksik veri anlamı kayıt sözleşmesinin parçasıdır. Dakikalık toplamı saatlik toplama yükseltmek toplamsal metriklerde mümkündür; ortalama CPU kullanımında örnek sayısıyla ağırlıklandırma gerekebilir. Sayaç (counter) türü metriklerde sıfırlama ve taşma olayları delta hesabını etkiler. TTL ile ham veriyi silmeden önce uzun dönem özetinin doğru ve eksiksiz oluştuğu doğrulanmalıdır.

ClickHouse 26.9'daki TimeSeries/PromQL gelişmeleri özel önizleme kapsamındadır ve standart MergeTree tablosunda zaman alanıyla SQL sorgulama yapılmasının yerine zorunlu bir mimari öneri oluşturmaz. Metrik modeli, etiketler ve ölçüm değerlerinden meydana gelen serilerin kardinalitesi üzerinden boyutlandırılır. Aynı metrikte servis, host ve endpoint etiketlerinin serbestçe çoğalması, düşük gecikmeli raporlama için beklenen bellek ve indeks maliyetini yükseltebilir.

Zaman serisi downsampling işleminde ham `avg` değerlerini yeniden ortalamak doğru toplam ortalamayı vermeyebilir. Bir dakikalık özetin `(sum, count)` çifti taşındığında beş dakikalık ortalama `Σsum / Σcount` ile hesaplanır. Aynı ilke birleştirilebilir quantile ve distinct durumları için fonksiyonların uygun `State`/`Merge` biçimlerini gerektirir. Silinen veya geç gelen olaylarda var olan özetlerin kendiliğinden ters işlemle düzelmediği ayrıca değerlendirilir.

### 33.3. Siber Güvenlik ve Ağ Olaylarının Tarihsel Analizi

Siber güvenlik olaylarında kaynak IP, hedef IP, protokol, kategori ve zaman öne çıkan boyutlardır. Anomali algılama sonuçları verinin hangi sürüm/filtreyle oluşturulduğunu kaydetmelidir. Veri yoğunluğu yüksek olsa bile olay kimlikleri ve evidence lineage kaybolmamalıdır.

İstatistiksel sapma, değişim noktası ve anormal olay örüntülerinin karar kuramı [Anomali Algılama](/anomali-algilama) notuyla ilişkilidir.

Siber güvenlik olaylarında kaynak IP, hedef IP, port, protokol, oturum kimliği ve olay zamanı tipli alanlar olarak saklanabilir. Adresleri yalnız String içinde tutmak adres aralığı ve ağ öneki işlemlerini zorlaştırabilir. Tek olayın tekrar aktarılması saldırı frekansını olduğundan yüksek gösterebilir; olay kimliği ve veri alımı kaynak bilgisi bu nedenle önemlidir. Analitik bulguların adli delil bütünlüğü gerektirmesi durumunda ClickHouse raporu kanonik delil yerine geçmez; kaynak kayıt ve doğrulama zinciri korunur.

### 33.4. Gözlemlenebilirlik, Telemetri ve Metrik Agregasyonu

Telemetri bir sistemin CPU, disk, ağ ve görev akışı ölçülerini içerebilir. Metrik etiketlerinin kardinalitesi kontrolsüz büyürse gruplama belleği ve fiziksel depolama maliyeti yükselir. İşlemsel kritik servis üzerinde ölçüm üretiminin ek gecikme ve güvenlik maliyeti olabilir; ayrı analitik yol gerekli olup olmadığı iş yüküne göre kararlaştırılır.

Gözlemlenebilirlik verisi log, metric ve trace olmak üzere farklı yapıdadır. Log metni yüksek çeşitlilik gösterirken metric zaman serisi çoğu kez sayısal agregasyona daha elverişlidir. Trace verisinde parent-child ilişkisinin birleştirilmesi farklı JOIN ve sorgu erişim örüntüleri yaratır. Üç veri ailesini tek büyük tabloya sıkıştırmak şema ve codec avantajlarını azaltabilir. Telemetri tasarımında alım hızı, retention ve seçilen sorgu ailesi ayrı karakterize edilmelidir.

Zaman serisi metriklerde cardinality, etiket birleşimlerinin sayısıyla büyür: 200 servis × 1000 host × 5 ortam = 1 milyon seri. Her seri için saniyede bir nokta tutulursa günlük olay sayısı 86,4 milyardır. Bu hesap, yalnız kullanılan etiketlerin çarpımına dayanan üst sınır yaklaşımıdır; gerçek etkin birleşimlerin sayısı daha düşük olabilir. Sabit etiket sözleşmesi ve retention katmanları depolama maliyetinin belirleyicileridir.

Log gövdesi, sayısal metrik ve trace span için aynı fiziksel sıralama her zaman uygun değildir. Metrikler genellikle `(metric_name, tags, timestamp)`, loglar `(service, timestamp)` ve trace parçaları `trace_id` erişimi gerektirebilir. Birleşik analitik ortamda tablo başına farklı sıralama anahtarı kullanılması, verileri fiziksel olarak tek tabloda birleştirmekten daha doğru bir seçenek olabilir.

### 33.5. Gerçek Zamanlı Gösterge Panoları ve API Sunumu

Gösterge paneli sorguları aynı zaman penceresini çok sık okuyorsa aggregate state veya projection etkili olabilir. API sunumu veri tazeliğini ve önbellek kaynaklı eski sonuç riskini belirtmelidir. Kullanıcı etkileşiminde p95/p99 sorgu gecikmesi tek sorgu minimumundan daha değerlidir.

Gerçek zamanlı dashboard'un ekrandaki yenileme aralığı analitik veri tazeliğinden farklıdır. Bir panel her 2 saniyede sorgu gönderse de son kaynak işlem onayı'i 30 saniye geriden gelebilir. Çok kullanıcıya aynı ağır sorgunun tekrar tekrar çalıştırılması sorgu kuyruğunu büyütebilir; uygun özet tablo veya kontrollü önbellek gerekebilir. İstek başına maksimum veri aralığı, toplulaştırma granularity ve sorgu timeout'ı API sözleşmesinde tanımlanmalıdır.

### 33.6. Milyar Satırlı Olay Şeması, Sorgular ve İndeks Analizi

Milyar satırlı şemada tablo `event_time DateTime64(3,'UTC')`, `service_id UInt32`, `event_type LowCardinality(String)`, `duration_ms UInt32` gibi tiplerle tasarlanabilir. `PARTITION BY toYYYYMM(event_time)` ve `ORDER BY (service_id, event_time)` servis/zaman filtreleri için başlangıç hipotezidir; gerçek dağılımla ölçülmeden optimal ilan edilmez.

Olay veri kümesinde doğal grain “kaynak sistemin ürettiği tek olay” olabilir; fakat yeniden teslim edilen aynı olay ikinci fiziksel satıra dönüşebilir. Analitik şema `event_id`, `source_id`, `tenant_id`, `event_time`, `ingested_at`, `event_type`, `status_code` ve gerekirse `version` gibi alanları taşıyabilir. `event_id`nin evrensel tekilliği kaynak sözleşmesiyle garanti edilmemişse düz `uniqExact(event_id)` bütün kaynaklar için tekil olay sayısını vermeyebilir. Bileşik anahtar veya kaynak bazlı kimlik gerekir.

Örnek fiziksel tasarım:

```sql
CREATE TABLE event_analytics
(
    event_time DateTime64(3, 'UTC'),
    source_id UInt32,
    tenant_id UInt32,
    event_id UUID,
    event_type LowCardinality(String),
    status_code UInt16,
    processing_time DateTime64(3, 'UTC')
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(event_time)
ORDER BY (tenant_id, event_time, event_type, source_id, event_id)
TTL event_time + INTERVAL 180 DAY;
```

Bu örnek, tenant ve zaman bazlı sorguların baskın olduğu varsayımıyla kurulmuştur; kimlik üzerinde tekil arama veya bütün tenant'larda salt zaman aralığına göre sorgulama için otomatik üstün değildir. `processing_time` olayın analitik sisteme işlendiği zamanı temsil eder; event-time'a göre TTL uygulanırsa geç gelen olayın saklama süresi kısalabilir. Arşivleme kuralı işleme tarihini esas alıyorsa TTL alanı ayrıca seçilmelidir.

```sql
SELECT
    tenant_id,
    toStartOfHour(event_time) AS hour,
    count() AS events,
    countIf(status_code >= 500) AS errors,
    round(100.0 * errors / nullIf(events, 0), 3) AS error_pct
FROM event_analytics
WHERE tenant_id = 42
  AND event_time >= toDateTime64('2026-10-01 00:00:00', 3, 'UTC')
  AND event_time < toDateTime64('2026-10-02 00:00:00', 3, 'UTC')
GROUP BY tenant_id, hour
ORDER BY hour;
```

Buradaki `status_code ≥ 500` bir örnek sınıflandırmadır; gerçek olay kodunun semantiğine göre hata eşiği değişebilir. Aynı tablo ile 100 milyon, bir milyar ve daha yüksek satırlı denemelerde bütün alanlar değil yalnız sorgunun okuduğu sütunlar, seçilen veri parçası/granül sayısı ve kalıcı sıkıştırma ölçüleri raporlanmalıdır.

### 33.7. Oracle OLTP ve ClickHouse OLAP ile Çift Depolama Mimarisi

Oracle kullanıcı işlemlerini yönetirken ClickHouse log, zaman serisi veya tarihsel analitiği yürütür. CDC ile sıcak analitik kopyaya veri taşınabilir, eski veri TTL politikasıyla tutulabilir. Her iki ortamın sorumluluk sınırı, olay kimliği, anlık görüntü kesiti ve yeniden oluşturulabilirlik koşulu belgelenir.

Oracle OLTP ve ClickHouse OLAP çift veri katmanında uygulamanın hangi soruyu hangi sisteme yönelteceği açık olmalıdır. Hesap bakiyesi güncelleme, eşzamanlı mutasyon ve referans bütünlüğü Oracle üzerinde kalabilir; tarihsel sayım ve çok boyutlu rapor ClickHouse'a yönlendirilebilir. CDC kopyası zaman bakımından eski olabileceği için tekil işlem doğrulaması hedef kopyadaki son kayda dayanmamalıdır. Mimari başarı yalnız hızlı rapor değil kaynak OLTP'nin daha kararlı kaynak kullanımıyla çalışmasıdır.

### 33.8. Veri Soy Ağacı, Geri Yükleme ve Doğruluk

Veri soy ağacı bir analitik sonucun hangi kaynak/SCN/aralık ve dönüşüm sürümünden üretildiğini izlemeyi sağlar. Geçmiş veri yüklemesi geçmiş zamanı yeniden hesapladığında bir raporun eski ve yeni sürümü ayrıştırılır. Aynı veri tekrar işlendiğinde aggregate sonuçlarında mükerrerlik oluşmaması gerekir.

Lineage, tek bir çıktı satırının hangi kaynak, dönüşüm sürümü ve zaman kesitinden üretildiğini izlemeye yardım eder. Geçmiş veri yüklemesi işlemi eski kaynak verisini yeni dönüşüm mantığıyla tekrar üretirse eski ve yeni özetlerin karşılaştırılabilirliği bozulabilir. Her yükleme partisinin kaynak sınırı ve şema sürümü saklandığında hata tespiti ve seçici yeniden işleme kolaylaşır. Kaynak ve hedefte hash kıyaslaması yapılacaksa değer normalizasyonu ve sıralama semantiği sabit olmalıdır; ham satır sayımı tek başına yeterli değildir.

## Ünite 34: Deneysel Performans, Kapasite ve Maliyet Analizi

Tek bir sorgu süresi kapasiteyi açıklamaz. Eşzamanlılık arttıkça throughput, p50, p95 ve p99 birlikte ölçülerek doygunluk noktası bulunmalıdır.

![Benchmark throughput latency animasyonu](https://alikoker.com.tr/svg/benchmark-latency-throughput.svg "Benchmark throughput ve latency")


Performans iddiası ancak doğrulanabilir veri kümesi, eşdeğer sorgular, tekrarlanabilir test ortamı ve hata ölçüsüyle anlamlıdır. ClickHouse'un belirli analitik sorgularda çok yüksek hız sağlayabilmesi, bütün ürünlerle ve bütün sorgularla evrensel bir çarpan sunmaz. Ölçüm; sorgu gecikme dağılımı, işlem hacmi, verinin gerçek sıkıştırılmış boyutu, veri alımı CPU gideri, kaynak OLTP üzerindeki yük ve kurtarma kapasitesini birlikte kapsar.

Gerçek performans değerlendirmesi üç soruyu yanıtlar: aynı sonuç mu hesaplandı, ne kadar kaynak tüketildi ve bu maliyet aynı iş yükünde tekrarlanabiliyor mu? Analitik karşılaştırmada basit tek sorgu karşılaştırması toplam sahip olma maliyeti hesabına eşit değildir. ClickHouse ve Oracle'ı eşit veride çalıştırırken verinin şema düzenleri farklı olabilir; bu fark ürünün iç tasarımını temsil eder, ancak yalnız ilan edilen süreyi yeterli bilimsel kanıt yapmaz. Sorgu önbelleği yanlışlıkla bir sistemde sıcak, diğerinde soğuk tutmak ciddi yanlılık doğurur. Sorgu başına enerji, CPU-saniye, GB okuma ve depolama maliyeti ayrı toplanmalıdır. Sonuçların anlamlılığı deneyin örneklem büyüklüğü, değişkenlik, hipotez seçimi ve güven aralığıyla yorumlanır. "1000× hızlanma" veya "5× maliyet" gibi oranlar yalnız sınanmış belirli konfigürasyon için geçerli olabilir.

### 34.1. Yeniden Üretilebilir Başarım Testi ve İş Yükü Tasarımı

Başarım karşılaştırması için veri üretim yöntemi, satır sayısı, null/cardinality dağılımı, kullanılan SQL, ClickHouse sürümü, şema ve donanım bütünüyle belirtilir. TPC-H/TPC-DS karar desteği sorgu aileleri, ClickBench analitik sorgu profili sağlar; hiçbir başarım karşılaştırması bütün üretim iş yüklerini temsil etmez.

Tekrarlı istemci başarım karşılaştırmasını:

```bash
clickhouse-benchmark --host localhost --concurrency 8 --iterations 100 --query "SELECT count() FROM default.events"
```

Sonuç, seçilen sorgu ve concurrency için geçerlidir. Bu testten bütün üretim sorguları ve OLTP karşılaştırmaları için genel hız çarpanı türetilemez.

İki sistemin eşdeğerliğini sağlamak için önce sorgunun semantiği dondurulur. Örneğin `COUNT(*)` için fiziksel mükerrerlerin sayılması mı, mantıksal olayların sayılması mı istendiği tanımlanmadan karşılaştırma geçerli değildir. `COUNT(DISTINCT ...)` algoritmasının yaklaşık veya kesin oluşu, zaman dilimi dönüşümü, boş değer ve JOIN çokluğu da sonuçlarda belirleyicidir. Sorgu setinde veri okuma, filtreleme, geniş GROUP BY, JOIN, top-k, zaman serisi, yüksek cardinality ve doğrudan metin arama ayrı iş yüklerini temsil etmelidir.

Bir başarım karşılaştırması yürütmesinde kullanılabilecek temel veri düzeni şu şekildedir: `dataset_version`, `server_version`, `schema_version`, `query_id`, `query_text`, `run_index`, `cache_state`, `concurrency`, `latency_ms`, `read_bytes`, `peak_memory_bytes`, `result_digest`. `result_digest` karşılaştırma yordamının amaçları için uygulama tarafında üretilir; SQL'e hash zorunluluğu getirmez. Başlangıç ölçümü, tüm yöntemlerde sonuç doğruluğu sağlandıktan sonra başlatılır. Üretici başarım karşılaştırması sonuçları bilimsel karşılaştırmada ikincil referans olarak kullanılabilir; kullanıcı iş yükünü temsil etmeyen ölçümler kapasite veya yatırım kararı için tek dayanak yapılmaz.

Karşılaştırma veri kümesinin “aynı sayıda satır” içermesi yeterli değildir. Aynı alanların aynı bilgi içeriğiyle saklanması, `NULL` ve zaman dilimi davranışlarının uyuşması, yaklaşık ve kesin toplulaştırma fonksiyonlarının ayrılması ve sorguların aynı mantıksal sonuçları üretmesi gerekir. ClickHouse'ta ham olay tablosuyla ölçülen süre başka sistemde önceden özetlenmiş cube veya önbellek tablosuyla karşılaştırılıyorsa ön hesaplamanın veri alımı/refresh maliyeti rapora eklenir.

Sorgu sayısı Q, tekrar sayısı r, ölçülen süreler `T(q,i)` olsun. Her sorgu için medyan ve p95 ayrı hesaplanmalı; çok farklı ölçeklerdeki sorguların süreleri tek aritmetik ortalamada birleştirilmemelidir. İyileştirme faktörleri `S(q)=T_ref(q)/T_test(q)` biçiminde sorgu başına raporlanır. Bir sistemin hız oranlarının geometrik ortalaması kullanılabilir fakat hangi sorguların dahil edildiği ve başarısız/timeout sorguların nasıl işlendiği açıkça verilmelidir. Warm-up, sorgu önbelleği, dosya sistemi önbelleği ve first-run recompilation etkileri ayrı deney grupları olarak kaydedilir.

### 34.2. Sıcak–Soğuk Önbellekler, Eşzamanlılık ve Kuyruk Gecikmesi

İlk çalıştırmadaki soğuk önbellekle elde edilen sonuçlar ile sonraki sıcak önbellek sonuçları ayrı raporlanır. Sorgu concurrency arttıkça disk ve memory kuyruğu büyüyebilir. Tek sorgu testinin p99'u trafik altında işletim davranışının p99'una eşit değildir.

A/B deneyi için aynı data anlık görüntüyü ile her şemada en az 30 tekrarlı sorgu koşulabilir; 30 sayısı evrensel asgari yeterlilik sınırı değil başlangıç tasarım örneğidir. Sunucu yeni başlatılmış soğuk önbellek koşulları ile tekrarlanmış sıcak önbellek koşulları ayrı tutulur. Deneyin sorgu sırası randomize edilerek zamana bağlı etmenlerin tek şemaya yığılması azaltılabilir. Yük altında p99 kararlılığı için örnek sayısı, sorgu karışımı ve güven aralığı daha büyük deney gerektirir. Oracle ve ClickHouse karşılaştırmasında eşdeğer filtre ve sonuç garantisi sağlanmadıysa açıklanan hızlanma oranı geçersizdir.

Sıcak önbellek testi, verinin tekrar erişimde bellekte kalabileceği üretim yüklerini; soğuk test ise ilk erişim ve uzak depolama maliyetini temsil eder. Bütün test koşularının aynı durumda başlaması gerekir. Tek sorgulu gecikme deneyiyle çok kullanıcılı concurrency deneyi ayrı tasarlanmalıdır. Eşzamanlı sorgu sayısı arttığında toplam işlem hacmi yükselirken p99 gecikme daha erken bozulabilir; doygunluk noktası her iki metrikle belirlenir.

### 34.3. P50/P95/P99, İşlem Hacmi ve Sorgu Doğruluğu

`p50` ortanca süreyi, `p95` ve `p99` gecikme dağılımının kuyruk bölgesini ifade eder. Sonuçların karşılaştırılmasında ölçüm penceresi, eşzamanlılık, veri dağılımı, sorgu parametreleri ve sonuç doğruluğu sabitlenir. Hata veya timeout ile sonlanan sorguların tamamen çıkarılması, hizmetin kullanıcıya sunduğu deneyimi gerçeğinden iyi gösterebilir.

p99, sıralanmış N gözlemde yaklaşık yüzde 99 konumundaki değerdir; N=100 olduğunda yalnız en üst birkaç gözleme duyarlı olduğundan tek koşuyla güvenilir bir kapasite kararı verilmez. Tekrarlı deneylerde medyan ve kuyruk yüzdelikleri güven aralıklarıyla raporlanabilir; bootstrap kullanıldığında gözlemlerin bağımsızlık ve iş yükü durağanlığı varsayımları incelenmelidir. Sabit hızla trafik üretildiği karşılaştırmalı başarım testlerinde servis gecikmesi nedeniyle atlanmış isteklerin ölçülmemesi *coordinated omission* oluşturur. Açık çevrim istek üretimi ile kapalı çevrim eşzamanlı istemci deneyi farklı performans sorularını yanıtlar.

Sorgu doğruluğunda `count()`, `sum()`, yüzdelikler ve benzersiz sayımlar aynı veri kesitinden hesaplanmalıdır. Yaklaşık `uniq` veya quantile sonuçları için hata toleransı önceden bildirilirken, exact sonuçlarda veri tipi, NULL ve zaman dilimi semantiği eşleştirilir. Bir sorgunun daha hızlı ama yanlış sonuç vermesi optimizasyon kazanımı değildir. Deney raporunda sorgu sayısı, başarılı/başarısız istekler, hız sınırı, sürüm, donanım, soğuk/sıcak önbellek, arka plan birleştirme yükü ve kullanılan sorgu planı birlikte bulunmalıdır. [26, 27]

### 34.4. Depolama Sıkıştırması, TB Başına Maliyet ve Kaynak Kullanımı

Sıkıştırma oranı ham giriş baytı / sıkıştırılmış fiziksel bayt olarak tanımlanabilir; üstveri, replikalar ve yedekler kapasiteyi büyütür. Disk fiyatının düşmesi CPU veya ağ maliyetinin de aynı oranda düştüğü anlamına gelmez. Cost/TB hesaplarında kullanılabilir kapasite esas alınır.

Depolama maliyeti üç ayrı düzeyde hesaplanmalıdır: tablodaki sıkıştırılmış aktif veri parçası baytları, replikasyonla çoğaltılmış disk baytları ve yedekleme/arşivleme katmanının tuttuğu baytlar. ClickHouse `system.parts` üzerinden alınan aktif veri parçası toplamı, object-store anlık görüntü, geçici birleştirme alanı ve yedek retention maliyetinin tamamına eşit değildir. Üç replica'lı bir shard'da tekil veri boyutunun yaklaşık üç kopyası bulunabilir; sıkıştırma kazanımı fiziksel kopyalama gereksinimini ortadan kaldırmaz.

Örnek olarak 100 TiB ham olay verisi 8 kat sıkıştırılırsa ana veri yaklaşık 12,5 TiB olur. Üç replica ile ana veri kopyalarının toplamı yaklaşık 37,5 TiB'ye çıkar; indeks, üstveri, geçici birleştirme alanı ve yedekler bu örnek hesaba dahil değildir. Maliyet modeli ayrıca CPU-saat, ağ aktarımı, nesne GET/LIST çağrıları ve operasyon personelinin süresini içermelidir. Oranların doğru hesaplanması için GiB/TiB ile GB/TB birimleri birbirine karıştırılmamalıdır.

### 34.5. CPU, Disk G/Ç, Ağ ve Bellek Darboğazları

CPU doygunluk hesaplama yükünü; disk I/O doygunluk tarama ve birleştirme baskısını; network doygunluk distributed dağıtık veri değişimi veya uzak depolamayı gösterebilir. Bellek kullanımı hash JOIN, sorting ve önbellek nedeniyle yükselir. Profil, hangi kaynak doygunken sorgunun beklediğini göstermelidir.

CPU doygunluğu, disk I/O, bellek ve ağ darboğazları benzer sorgu gecikmesi artışını farklı mekanizmalarla oluşturabilir. `read_bytes` düşükken sorgu yavaşsa hash JOIN belleği, ifade CPU'su veya sonuç aktarımı incelenir. `read_bytes` yüksek ve disk doygunsa veri atlama ve sütun pruning önemlidir. Dağıtık sorguda ara sonuç boyutu ağı doyurabilir; her node'daki CPU yüzdesi düşük olsa bile coordinator üzerinde seri birleştirme sınıra dönüşebilir.

Bir deneyin sonuç tablosunda yalnız ortalama gecikme değil aşağıdaki bilgiler bulunmalıdır: ClickHouse sürümü ve ayarları, CPU modeli ve çekirdek sınırı, RAM, SSD/NVMe konfigürasyonu, sorgu metni, veri parçası/bölüm sayıları, sorgu sonucu doğrulama yöntemi, soğuk/sıcak önbellek durumu, eşzamanlı sorgu adedi, ölçüm sayısı ve güven aralığı. p99 için yalnız 10 gözlemden kararlı tahmin çıkarılamaz; yüzdelik değerlerin istatistiksel gücü ve kuyruk gecikmesinin zamansal bağımlılığı dikkate alınmalıdır.

Sıralı başarım karşılaştırması koşularında ilk sorgunun önbelleği ısıtması ve arka plan birleştirme işlerinin sonrakileri etkilemesi sistematik yanlılık üretir. Alternatifleri farklı sıralarda, benzer veri kesitlerinde, tekrarlarla çalıştırmak ve tekil ölçümleri saklamak gerekir. Karşılaştırılan sorguların aynı sonuç kümesini üretmesi, her sistemin doğru fiziksel tasarımla kurulması kadar zorunlu bir koşuldur.

### 34.6. Veri Ekleme ve Sorgu Hızı Arasındaki Maliyet Dengesi

Daha fazla projection/MV hızlı SELECT sağlayabilir ancak INSERT CPU ve write amplification'ı artırır. Yüksek eşzamanlılıkta daha yüksek read işlem hacmi hedefi veri alımı backlog doğurabilir. İş yükü ağırlıklı toplam maliyet seçilen tasarımın ekonomik ölçüsüdür.

Büyük INSERT blokları veri parçası sayısını azaltırken tek isteğin başarısız olması durumunda tekrar gönderilecek veri büyüklüğünü artırır. Ön hesaplanmış projection veya materyalleştirilmiş görünüm eklemek okuma hızını yükseltebilir, fakat INSERT yolunda ek CPU ve disk yazımı oluşturur. Yalnız sorgu hızını maksimize eden şema en yüksek sürdürülebilir veri alımı işlem hacmi'unu sağlamayabilir. Üretim kararı iki yöndeki talep dağılımına ve kaynak payına göre verilmelidir.

Yazma–okuma değiş tokuşu basitçe iki toplamla temsil edilebilir: C_toplam = N_insert × C_insert + N_select × C_select + C_bakım. Yeni bir projection sorgu maliyetini ΔC_select kadar azaltırken INSERT maliyetini ΔC_insert kadar artırıyorsa toplam kazanç için N_select × ΔC_select > N_insert × ΔC_insert + ΔC_bakım koşulu gerekir. Buradaki maliyetlerin aynı birimle, örneğin CPU-saniye ve amortize edilmiş disk/altyapı maliyetiyle ifade edilmesi gerekir.

Yazma hacmi gün içinde değişiyorsa ortalama INSERT/s yerine pik veri alım hızı ve birleştirme backlog büyümesi esas alınmalıdır. Kalıcı veri parçası birikimi, ilk gün hızlı çalışan projection tasarımının birkaç hafta sonra yavaşlamasına yol açabilir. Uzun süreli yük testi bir sorgu planının ilk dakikadaki başarısından daha fazla üretim bilgisi sağlar.

### 34.7. TCO, Lisans, Bulut–Yerinde Kurulum ve Afet Kurtarma Maliyeti

Toplam sahip olma maliyeti (TCO), lisans bedeli ile sorgu başına işlem gücü maliyetinin toplamı değildir. Yıllık karşılaştırmada işlemci/RAM, kalıcı veri ve kopyalar, ağ çıkışı, ingest hattı, yedekleme, kurtarma testleri, operasyon emeği ve beklenen erişilemezlik maliyeti birlikte ele alınır. Açık kaynak dağıtımda lisans bedeli sıfır olabilir; buna karşılık işletim ve kapasite sorumluluğu kullanıcıdadır.

Örneğin 100 TiB mantıksal veri için 4:1 sıkıştırma oranı elde edilirse ana kopya yaklaşık 25 TiB olur. Üç tam fiziksel veri kopyası yaklaşık 75 TiB ham depolama gerektirebilir; nesne depolama üzerinde üstveri, silme gecikmesi, anlık görüntü ve yedekler bu hesabı değiştirebilir. Yönetilen hizmetin paylaşılan depolama mimarisi, klasik üç bağımsız replika varsayımıyla modellenmemelidir. Verinin `INSERT` anındaki üretim maliyeti ve sorgulanabilir hale gelme gecikmesi de bütçeye dahil edilir.

Karşılaştırma sabit bir veri hacmine değil, büyüme eğrisine dayanmalıdır. `D(t) = D₀ + r×t` modeliyle günlük yeni veri r, saklama süresi ve sıkıştırma oranı birlikte değerlendirilir; TTL ve tiering kaynak kullanımını değiştirebilir. Aynı RPO/RTO, p95 sorgu gecikmesi ve saklama garantisi sağlanmadan hesaplanan iki TCO değeri eşdeğer hizmetleri temsil etmez.

### 34.8. A/B Şema Karşılaştırmaları ve Sonuçların Yorumlanması

A/B şema deneyinde sıralama anahtarı, bölüm, codec veya projection gibi tek temel değişken ayrı sınanır. Aynı veri anlık görüntü ve sorgu seti üzerinde ölçülür. Ölçülen fark hem merkezi eğilim hem kuyruk gecikmeleriyle raporlanır; varyans ve güven aralığı değerlendirilir.

Üretici tarafından raporlanan iyileştirme katsayısı `S = T_referans/T_yeni` biçiminde hesaplanır; `S=1000` için referans sorgu süresinin yeni sürenin bin katı olması gerekir. Aynı oranın depolama, CPU kullanımı ve maliyet üzerinde geçerli olması zorunlu değildir. Örneğin depolama tasarrufu oranı `(B_referans−B_yeni)/B_referans`, disk kullanımının yarıya inmesi için `%50` olur; bunun karşılığı 2 kat daha az alan kullanımıdır. `5× cost savings` bir ürünün pazarlama ifadesidir ve bütçe modelinde ilgili harcama kalemlerinin oranı açıkça tanımlanmalıdır.

ClickHouse'un 2026 tarihli en iyi uygulamalar yazısında doğru birincil anahtarın örnek testte **347 kat daha az veri taraması**, uygun veri tiplerinin **%12 daha az depolama ve %50 daha kısa sorgu süresi**, gereksiz bölüm seçiminin **46 kat yavaşlama** oluşturabildiği belirtilmiştir. Bu veriler, aynı ürün içinde fiziksel tasarımın etkisini gösteren örnek çalışmaya aittir; bütün veri kümelerinin bu katsayılara ulaşacağını göstermez. Kaynak: https://clickhouse.com/blog/10-best-practice-tips

Başarım karşılaştırması raporunda en azından veri kümesinin provenance bilgisi, şema, sıralama ve bölüm anahtarı, materyalleştirilmiş görünüm/projection durumu, dosya sıkıştırması, ClickHouse ve karşı sistem sürümleri, CPU/RAM/disk türü, node sayısı, önbellek durumu, sorgu semantiği, tekrar sayısı, güven aralıkları, p50/p95/p99, soğuk/hot ayrımı ve toplam harcama bileşenleri bulunmalıdır. ClickBench ve CostBench metrikleri aynı soruyu ölçmez: birincisi belirli analitik sorguların ve depolamanın karşılaştırılmasına, ikincisi verinin içeri alınması ve sorguya hazır tutulmasını da kapsayan maliyet-performans yaklaşımına yönelir. Kaynaklar: https://benchmark.clickhouse.com/ ; https://clickhouse.com/benchmarks/costbench

A/B deneyinde iki şema aynı mantıksal sorgu sonucunu üretmeli ve eşdeğer veri yüküyle değerlendirilmelidir. `ORDER BY` değişimi ile codec değişimi birlikte uygulanırsa kazanımın hangi nedenden geldiği ayrıştırılamaz. Kontrollü deneyde tek bir ana faktör değiştirilip okunan byte, CPU zamanı, p95/p99, depolama boyutu ve ekleme işlem hacmi raporlanabilir. Çok etkenli tasarımda etkileşimler ayrıca modellenir; rastgele tek bir iyi koşu üzerinden genel sonuca gidilmez.



ClickHouse'un Eylül 2026 CostBench çalışması, yalnız sorgu süresini değil yeni gelen verinin sorgulanabilir hale getirilmesi maliyetini de kapsar. Üretici, sürekli olarak 1 milyon satır/saniye hedefle 100 milyardan fazla borsa kotasyonu işlenen karşılaştırmada ClickHouse Cloud'un test edilen alternatiflere göre dolar başına uçtan uca performansta 412–1996 kat avantaj bildirdiğini açıklamıştır. Deney, ClickHouse Cloud, Snowflake, Databricks, BigQuery ve Redshift Serverless için yayımlanan belirli mimariler ve faturalama modelleriyle sınırlıdır. Kaynak: https://clickhouse.com/blog/costbench-real-time-performance-per-dollar

Sorgu sonuçları doğru ve veri tazeliği aynı hedefi sağlıyorsa veri alımı hazırlama maliyeti rapora dahil edilmelidir. Bir sistem daha ucuz depolama kullanırken query-ready gecikmesini artırabilir; dolayısıyla maliyet, kaynak veri gelmesinden doğrulanmış sonucun üretilmesine kadarki hizmet zincirini kapsamalıdır.

Fiziksel tasarım deneylerinde A ve B sürümleri aynı kaynak veri kesitinden üretilmeli, INSERT maliyetleri de sorgu maliyetlerine eklenmelidir. Örnek karar metriği `C = N_okuma × ortalama_okuma_maliyeti + N_yazma × ortalama_yazma_maliyeti + C_bakım` şeklinde tanımlanabilir. Sorgu sonuçları birebir eşdeğer, veri tazeliği aynı ve veri saklama kuralları eşit değilse toplam maliyet farkı anlamlı bir kıyaslama oluşturmaz.

Dağılımın p99 değeri tek çalıştırmayla tahmin edilemez. Veri önbelleği ısıtma, arka plan birleştirme durumu ve dış sistemdeki CDC gecikmesi ölçüm başlangıcında kayda alınmalıdır. Çok çekirdekli iki sunucu arasında salt işlem hacmi karşılaştırması yapılırken kullanılan toplam CPU-saniye ve depolama G/Ç miktarı da raporlanır. Kaynak: https://benchmark.clickhouse.com/ ve https://clickhouse.com/benchmarks/costbench.

ClickHouse 26.10 sürüm sunumu üç farklı optimizasyonun farklı darboğazlara yöneldiğini göstermektedir: 100 milyon tekil değer üzerinde Robin Hood hashing bellek ve CPU maliyetini; string filtreleme gereksiz nesne üretimini; Top-K eşik aktarımı ise okunan veri miktarını azaltmıştır. Bu örnekleri tek bir “26.10 sürümü x kat hızlıdır” sonucuna dönüştürmek metodolojik olarak geçersizdir. Birinci deneyde hash tablosunun doluluk oranı, ikincide filtre seçiciliği, üçüncüde sıralama anahtarı ve granül atlama kabiliyeti sonucu belirler. Sorgular aynı sonuç kümesini üretse bile optimizer'ın kullandığı yol ve sistemin kaynak sınırı raporda belirtilmelidir. [41]

Başarım karşılaştırması kapsamının bir diğer sınırı, işlem içi analitik (chDB, DuckDB), çok düğümlü ClickHouse ve belge arama sistemlerinin farklı iş yükleri için tasarlanmış olmasıdır. Saniye başına sorgu karşılaştırmaları yürütme motoru dışında veri alımı, veri formatı dönüştürme, indeks inşa süresi, depolama kopyası ve sonuç aktarımı maliyetlerini dışarıda bırakıyorsa toplam sistem kazanımını göstermez. Vektör ANN deneylerinde ayrıca recall@k, indeks oluşturma süresi ve bakım maliyeti raporlanır. Aynı gecikmede daha az kaynak kullanımı, ancak sorgu doğruluğu ve veri tazeliği eşdeğer olduğunda anlamlı maliyet avantajıdır. [26, 27, 47, 48]

### 34.9. Analitik Geçiş Kararı ve Kaynak Sisteme Etkileri

Analitik geçiş kararı mevcut Oracle kaynağında ölçülen CPU/I/O etkisi, CDC lag, ClickHouse doğruluk mutabakatı, analitik p95/p99 ve TCO ile verilir. Orijinal OLTP veri kaynağı ve yazma semantiği korunur. Yalnız ham sorgu süresine göre karar vermek operasyon maliyetini ve veri tazeliğini eksik değerlendirir.

Analitik yükün ClickHouse'a taşınması kararında kaynak Oracle/Exadata üzerindeki CPU ve I/O rahatlaması, CDC log madenciliğinin kaynak maliyetiyle birlikte hesaplanır. Hedef ClickHouse'ta sorgu sonucu aynı olsa bile tazelik ve tarihsel doğruluk hedefleri sağlanmıyorsa geçiş tamamlanmış sayılmaz. Ölçüm dönemi boyunca kaynak işlem p95/p99 gecikmesi, hedef sorgu p95/p99 gecikmesi, veri gecikmesi ve toplam altyapı maliyeti birlikte izlenir. Geçişin kademeli olması hem veri modeli hem operasyon riskini azaltır.

## Kaynakça

1. Boncz, P.; Zukowski, M.; Nes, N. (2005). MonetDB/X100: Hyper-Pipelining Query Execution. *CIDR*, 225–237. https://www.cidrdb.org/cidr2005/papers/P19.pdf
2. Brown, A. (2026). *What is chDB? In-process ClickHouse for Python*. ClickHouse Engineering, 8 Haziran 2026. https://clickhouse.com/resources/engineering/what-is-chdb
3. Chaudhuri, S.; Dayal, U. (1997). An Overview of Data Warehousing and OLAP Technology. *ACM SIGMOD Record*, 26(1), 65–74. https://doi.org/10.1145/248603.248616
4. ClickHouse. *Announcing General Availability of ClickHouse Full-text Search*. 10 Mart 2026. https://clickhouse.com/blog/full-text-search-ga-release
5. ClickHouse. *Backup and Restore*. https://clickhouse.com/docs/operations/backup
6. ClickHouse. *Choosing a Primary Key*. https://clickhouse.com/docs/best-practices/choosing-a-primary-key
7. ClickHouse (2023). *Choosing the Right Join Algorithm*. https://clickhouse.com/blog/clickhouse-fully-supports-joins-how-to-choose-the-right-algorithm-part5
8. ClickHouse. *ClickBench: A Benchmark for Analytical DBMS*. https://benchmark.clickhouse.com/
9. ClickHouse. *ClickHouse and PostgreSQL: Performance Comparison*. https://clickhouse.com/comparison/postgresql
10. ClickHouse (2026). *ClickHouse Concurrency: How to Size for User-facing Analytics*. https://clickhouse.com/resources/engineering/high-concurrency-sizing-user-analytics
11. ClickHouse (2026). *ClickHouse Projections Now Behave Like True Secondary Indexes*. https://clickhouse.com/blog/projections-secondary-indices
12. ClickHouse (2026). *ClickHouse release 26.8 — Background Queries, Pipelined SQL, User Query Log, Distributed Optimizations*. 10 Eylül 2026. https://clickhouse.com/blog/clickHouse-release-26-08
13. ClickHouse. *CostBench: An Open Data Warehouse Cost-Performance Benchmark*. https://clickhouse.com/benchmarks/costbench
14. ClickHouse. *Feature Journey: Indexing, Query Planning and Updates*. https://clickhouse.com/clickhouse/feature-journey
15. ClickHouse. *Introduction to ClickHouse; Architecture and Core Concepts*. https://clickhouse.com/docs/introduction-clickhouse
16. ClickHouse. *Materialized Views and Projections*. https://clickhouse.com/docs/materialized-views ; https://clickhouse.com/docs/data-modeling/projections
17. ClickHouse. *MergeTree Table Engine Family*. https://clickhouse.com/docs/engines/table-engines/mergetree-family/mergetree
18. ClickHouse. *Monitoring Asynchronous Inserts*. https://clickhouse.com/blog/monitoring-asynchronous-data-inserts-in-clickhouse
19. ClickHouse (2026). *Official ClickHouse Packages — Stable and LTS Release Channels*. 27 Ekim 2026 tarihinde erişildi. https://packages.clickhouse.com/
20. ClickHouse. *Parts and Partitions*. https://clickhouse.com/docs/parts ; https://clickhouse.com/docs/partitions
21. ClickHouse. *Performance and Query Optimization*. https://clickhouse.com/docs/optimize/query-optimization
22. ClickHouse (2025). *Release 25.7: Lightweight Updates and Deletes with Patch Parts*. https://clickhouse.com/blog/clickhouse-release-25-07
23. ClickHouse (2026). *Release 26.1: Deduplication of Asynchronous Inserts with Materialized Views*. https://clickhouse.com/blog/clickhouse-release-26-01
24. ClickHouse (2026). *Release 26.3: Asynchronous Inserts by Default*. https://clickhouse.com/blog/clickhouse-release-26-03
25. ClickHouse (2026). *Release 26.9: Incremental Refreshes, DISTINCT Disk Spilling, Scoped Tokens and Conditional LIMIT*. 23 Eylül 2026. https://clickhouse.com/blog/clickhouse-release-26-09
26. ClickHouse. *Security, Users, Roles and Access Control*. https://clickhouse.com/docs/operations/access-rights
27. ClickHouse. *System Tables and a Window into the Internals of ClickHouse*. https://clickhouse.com/blog/clickhouse-debugging-issues-with-system-tables
28. ClickHouse. *System Tables and Query Logging*. https://clickhouse.com/docs/operations/system-tables/query_log
29. ClickHouse (2026). *The Definitive Guide to ClickHouse Query Optimization*. https://clickhouse.com/resources/engineering/clickhouse-query-optimisation-definitive-guide
30. ClickHouse. *Update and Delete Operations*. https://clickhouse.com/docs/managing-data/update_mutations ; https://clickhouse.com/docs/managing-data/delete_mutations
31. ClickHouse (2026). *When to Denormalize, When to Join*. https://clickhouse.com/resources/engineering/when-to-denormalize-when-to-join
32. ClickHouse. *When to Use OPTIMIZE TABLE FINAL in ClickHouse*. 15 Haziran 2026. https://clickhouse.com/resources/engineering/clickhouse-optimize-table-final
33. Debezium. *Oracle Connector Documentation*. https://debezium.io/documentation/reference/connectors/oracle.html
34. Dolan, Y. (2026). *Top 10 Best Practices Tips for ClickHouse*. ClickHouse, 26 Mart 2026. https://clickhouse.com/blog/10-best-practice-tips
35. Elasticsearch. *The Elasticsearch Distributed Search and Analytics Engine*. https://www.elastic.co/docs
36. Gray, J.; Chaudhuri, S.; Bosworth, A.; Layman, A.; Reichart, D.; Venkatrao, M.; Pellow, F.; Pirahesh, H. (1997). Data Cube: A Relational Aggregation Operator Generalizing Group-By, Cross-Tab, and Sub-Totals. *Data Mining and Knowledge Discovery*, 1, 29–53. https://research.ibm.com/publications/data-cube-a-relational-aggregation-operator-generalizing-group-by-cross-tab-and-sub-totals
37. Melnik, S.; Gubarev, A.; Long, J. J.; Romer, G.; Shivakumar, S.; Tolton, M.; Vassilakis, T. (2010). Dremel: Interactive Analysis of Web-Scale Datasets. *Proceedings of the VLDB Endowment*, 3(1), 330–339. https://doi.org/10.14778/1920841.1920886
38. Milovidov, A. (2025). *ClickHouse Release 25.9: Vector Index and ANN Search*. Resmi sürüm sunumu. https://presentations.clickhouse.com/2025-release-25.9/
39. Milovidov, A. (2026). *ClickHouse Release 26.10*. Resmi sürüm sunumu, 22 Ekim 2026. https://presentations.clickhouse.com/2026-release-26.10/
40. Oracle. *Oracle Database: Concepts, Redo and LogMiner*. https://docs.oracle.com/en/database/oracle/oracle-database/
41. Schreiber, T. (2024). *ClickHouse vs. Elasticsearch: The Billion-Row Matchup*. ClickHouse Engineering, 7 Mayıs 2024. https://clickhouse.com/blog/clickhouse_vs_elasticsearch_the_billion_row_matchup
42. Schreiber, T. (2025). *How We Made ClickHouse UPDATEs 1,000× Faster (Part 3: Benchmarks).* ClickHouse Engineering, 7 Ağustos 2025. https://clickhouse.com/blog/updates-in-clickhouse-3-benchmarks
43. Schreiber, T. (2026). *How ClickHouse Became Fast at Joins*. ClickHouse, 3 Haziran 2026. https://clickhouse.com/blog/clickhouse-fast-joins
44. Schreiber, T.; Palacin, L. (2026). *CostBench: Putting Real-Time Analytics to the Test*. ClickHouse, 8 Eylül 2026. https://clickhouse.com/blog/costbench-real-time-performance-per-dollar
45. Schreiber, T.; Palacin, L. (2026). *Do you still need Elasticsearch for log analytics? ClickHouse says no.* ClickHouse Engineering, 23 Nisan 2026. https://clickhouse.com/blog/elasticsearch-log-analytics-clickhouse
46. Schulze, R.; Schreiber, T.; Yatsishin, I.; Dahimene, R.; Milovidov, A. (2024). ClickHouse — Lightning Fast Analytics for Everyone. *Proceedings of the VLDB Endowment*, 17(12), 3731–3744. https://doi.org/10.14778/3685800.3685802
47. Stonebraker, M.; Abadi, D. J.; Batkin, A.; Chen, X.; Cherniack, M.; Ferreira, M.; Lau, E.; Lin, A.; Madden, S.; O'Neil, E. J.; O'Neil, P. E.; Rasin, A.; Tran, N.; Zdonik, S. B. (2005). C-Store: A Column-oriented DBMS. *Proceedings of VLDB*, 553–564. https://dblp.org/rec/conf/vldb/StonebrakerABCCFLLMOORTZ05.html
48. Wheeler, D. (2026). *pg_clickhouse is the Fastest Postgres Extension on ClickBench*. ClickHouse. https://clickhouse.com/blog/pg_clickhouse-fastest-analytics-for-postgres

## Bu Çalışmaya Atıf

Köker, M. A. (2026). Analitik Veri Tabanı Sistemleri: OLAP ve ClickHouse. alikoker.com.tr. https://alikoker.com.tr/analitik-veri-tabani-sistemleri-olap-clickhouse

- BibTeX: https://alikoker.com.tr/analitik-veri-tabani-sistemleri-olap-clickhouse.bib
- RIS: https://alikoker.com.tr/analitik-veri-tabani-sistemleri-olap-clickhouse.ris
- CSL-JSON: https://alikoker.com.tr/analitik-veri-tabani-sistemleri-olap-clickhouse.csl.json
