📃
Tech White Papers
  • 📃White Papers
  • ðŸŠķApache
    • Kafka (EN)
      • Kafka Connect
      • Kafka Streams
      • ksqlDB
    • Ignite (TR)
      • Clustering
        • Baseline Topology
      • Thin Clients
      • Data Modeling
        • Data Partitioning
        • Affinity Colocation
      • Memory Architecture
      • Persistence
        • External Storage
        • Swapping
        • Snapshot
        • Disk Compression
        • Persistence Tuning
        • Change Data Capture
      • Cluster Snapshots
      • Data Rebalancing
      • Data Streaming
      • Using Key-Value API
        • Basic Cache Operations
        • Working With Binary Objects
      • Performing Transactions
      • Working with SQL
        • Understanding Schemas
        • Defining Indexes
        • Distributed Joins
      • Distributed Computing
      • Machine Learning
      • Using Continuous Queries
      • Using Ignite Messaging
      • .NET Specific
        • LINQ
        • Serialization
      • Working With Events
        • Events
      • Performance and Troubleshooting
        • Generic Performance Tips
        • Memory and JVM Tuning
        • Persistence Tuning
        • SQL Performance Tuning
        • Thread Pools Tuning
    • Pulsar (TR)
  • 📜Data
    • ClickHouse (TR)
    • QuestDB (TR)
  • Comparison
    • Pulsar vs Kafka
    • ClickHouse vs QuestDB
  • Architectural
    • Microservices
      • Design Principles
      • Design Patterns
Powered by GitBook
On this page
  • Storage model
  • Append model
  • Read model
  • Consistency and durability
  • Designated timestamp
  • SQL extensions
  • Timestamp search
  • Differences from standard SQL
  • Partitions
  • Symbol
  • Indexes

Was this helpful?

  1. Data

QuestDB (TR)

03/02/2023

PreviousClickHouse (TR)NextComparison

Last updated 2 years ago

Was this helpful?

QuestDB, timeseries ve event verileri için tasarlanmÄąÅŸ ilişkisel sÞtun tabanlÄą bir veritabanÄądÄąr. Gerçek zamanlÄą analitiğe yardÄąmcÄą olmak için timeseries için uzantÄąlarla birlikte SQL kullanÄąr.

Storage model

QuestDB, sÞtun tabanlÄą bir depolama modeli kullanÄąr. Veriler, her sÞtun kendi dosyasÄąnda ve kendi yerel biçiminde saklanan tablolarda saklanÄąr. Verilerin alÄąndığı sÄąrayla organik olarak alÄąnmasÄąna olanak sağlamak için her sÞtunun altÄąna yeni veriler eklenir.

Append model

QuestDB, her seferinde bir sÞtun ekler ve her biri aynÄą yÃķntem kullanÄąlarak gÞncellenir. SÞtun dosyasÄąnÄąn kuyruğu, RAM'deki bellek sayfasÄąna eşlenir ve sÞtun ekleme, etkin bir şekilde bir adreste bellek yazma işlemidir. Memory page tÞkendiğinde maplenmez ve yeni bir sayfa maplenir.

Bu yÃķntem, minimum kaynak karmaşasÄą ve tutarlÄą ekleme gecikmesi sağlar.

Read model

Tablo sÞtunlarÄąna rastgele erişilebilir. Sabit boyutlu veri tÞrlerine sahip sÞtunlar, kayÄąt numarasÄą basit bir bit kaydÄąrmayla bir dosya ofsetine çevrilerek okunur. SÞtun dosyasÄąndaki uzaklÄąk, daha sonra, gerekli değerin okunduğu tembel(lazy) mapped bir bellek sayfasÄąndaki bir kaymaya çevrilir.

Consistency and durability

QuestDB, tablo gÞncellemelerini atomik olarak uygulayarak tablo dÞzeyinde isolation ve consistency sağlar. Bir tabloya yÃķnelik gÞncellemeler, atomik bir işlemde commitlenen veya rollback uygulanan bir tablo işlemi bağlamÄąnda uygulanÄąr. Tablo gÞncellemeleriyle eşzamanlÄą sorgular, verileri tablo işleminin gerçekleştirilmesinden Ãķnce veya sonra olduğu gibi dÃķndÞrmeleri aÃ§ÄąsÄąndan tutarlÄądÄąr — sorgu sonucunda hiçbir ara kaydedilmemiş veri gÃķsterilmez.

Atomikliği garanti etmek için, her tablo ayrÄą bir dosyada bir last_comwed_record_count tutar. Genel olarak, herhangi bir tablo okuyucu asla işlem sayÄąsÄąndan daha fazla kayÄąt okumaz. Bu, isolation Ãķzelliğini etkinleştirir: burada kaydedilmemiş veriler okunamaz. Commitlenmemiş veriler doğrudan tabloya eklendiğinden, işlem boyutu yalnÄązca kullanÄąlabilir disk alanÄąyla sÄąnÄąrlÄądÄąr.

TÞm veriler eklendikten sonra, QuestDB commit() işlem sayÄąsÄąnÄąn hem multi-threaded hem de multi-process ortamlarda atomik olarak gÞncellenmesini sağlar. EşzamanlÄą okumalar Þzerinde minimum etki sağlamak için lock-free’dir.

Depolanan verilerin consistency gÞvencesi, QuestDB'nin anormal şekilde sonlandÄąrÄąlan işlemleri otomatik olarak onarmasÄąyla sÄąnÄąrlÄądÄąr. HenÞz kullanÄącÄą tanÄąmlÄą kÄąsÄątlamalar, kontroller ve tetikleyiciler desteklenmiyor.

VarsayÄąlan olarak QuestDB, işletim sistemi dÞzeyinde veri dayanÄąklÄąlığına(durability) gÞvenir ve işletim sistemini diske dirty pages yazmaya bÄąrakÄąr. Veri dayanÄąklÄąlığı, isteğe bağlÄą olarak senkron veya asenkron IO seçeneğiyle msync()'i çağırabilen commit() ile de yapÄąlandÄąrÄąlabilir. msync() çağrÄąlarÄą yalnÄązca sÞtun dosyalarÄą için yapÄąlÄąr, dolayÄąsÄąyla senkronizasyon/eşzamansÄąz tamamlama modlarÄą genel dayanÄąklÄąlığı artÄąrÄąrken, işletim sistemi hatalarÄą veya gÞç kaybÄą karÅŸÄąsÄąnda dayanÄąklÄąlığı garanti etmez.


Designated timestamp

QuestDB, designated timestamp ****olarak bir sÞtun seçme seçeneği sunar. Bu, zamana dayalÄą dil Ãķzelliklerinden ve yÞksek performanslÄą işlevselliklerden yararlanmak için tablolarÄąn hangi sÞtun tarafÄąndan indexleneceğini belirlemenizi sağlar.

Timestamp(columnName) fonksiyonu kullanÄąlarak designated timestamp seçilir:


SQL extensions

QuestDB, standart ANSI SQL'i uygulamaya çalÄąÅŸÄąr. Veri depolama modelini desteklemek ve timeseries analitiğinin anlamÄąnÄą basitleştirmek için QeustDB’de SQL genişletilmiştir.

LATEST ON

LATEST ON, bir SELECT deyiminin parçasÄą olarak belirli bir key veya key kombinasyonu için zaman damgasÄąna gÃķre en son girişi bulmaya yardÄąmcÄą olmak için sunulan bir yan tÞmcedir.

SELECT * FROM balances
WHERE balance > 800
LATEST ON ts PARTITION BY customer_id, currency;

SAMPLE BY

SAMPLE BY, efektif bir sÃķzdizimi ile zamana dayalÄą aggregationlar için kullanÄąlÄąr. Aşağıdaki kÄąsa sorgu, bir aylÄąk bÃķlÞmlere gÃķre bir hesap listesinden ortalama bakiyeyi dÃķndÞrÞr.

SELECT avg(balance) FROM accounts SAMPLE BY 1M

Timestamp search

SELECT * FROM scores WHERE ts IN '2018';

Differences from standard SQL

SELECT * FROM is optional

QuestDB'de SELECT * FROM kullanmak isteğe bağlÄądÄąr, yani SELECT * FROM my_table; my_table; ile aynÄą sonucu dÃķndÞrÞr. SELECT * FROM eklenmesi SQL'in daha eksiksiz gÃķrÞnmesini sağlarken, bu anahtar sÃķzcÞklerin Ã§ÄąkarÄąlmasÄąnÄąn sorgularÄą okumayÄą çok daha kolay hale getirdiği Ãķrnekler vardÄąr.

my_table;
-- equivalent to:
SELECT * FROM my_table;

GROUP BY is optional

GROUP BY yan tÞmcesi isteğe bağlÄądÄąr ve QuestDB iyileştiricisi SELECT yan tÞmcesinden grup bazÄąnda uygulama tÞrettiği için atlanabilir. Standart SQL'de, kullanÄącÄąlar aşağıdaki gibi bir sorgu yazabilir:

SELECT a, b, c, d, sum(e) FROM tab GROUP BY a, b, c, d;

Ancak, GROUP BY yan tÞmcesinde SELECT sÞtunlarÄąnÄąn bir alt kÞmesini gezmek gereksizdir ve bu nedenle gereksizdir. QuestDB SQL-lehçesindeki(dialect) aynÄą SQL şu şekilde yazÄąlabilir:

SELECT a, b, c, d, sum(e) FROM tab;

Implicit HAVING

Standart SQL'de HAVING kullanan daha karmaÅŸÄąk başka bir Ãķrneğe bakalÄąm:

SELECT a, b, c, d, sum(e)
FROM tab
GROUP BY a, b, c, d
HAVING sum(e) > 100;

QuestDB'nin lehçesinde alt sorgular, gereksiz yinelenen aggegationlar olmaksÄązÄąn daha kÞçÞk, daha okunabilir bir sorgu oluşturmak için imdada yetişir. HAVING işlevi dolaylÄą olarak şu şekilde elde edilebilir:

(SELECT a, b, c, d, sum(e) s FROM tab) WHERE s > 100;

Partitions

QuestDB, tablolarÄą zaman aralÄąklarÄąna gÃķre bÃķlÞmleme seçeneği sunar. Her aralÄąk için veriler ayrÄą dosya kÞmelerinde saklanÄąr.

Özellikler

  • KullanÄąlabilir partition intervalleriNONE, YEAR, MONTH, DAY, veHOUR ’dur.

  • Partition dizinleri(directory) için adlandÄąrma kuralÄą aşağıdaki gibidir:

    Table Partition
    Partition format

    HOUR

    YYYY-MM-DD-HH

    DAY

    YYYY-MM-DD

    MONTH

    YYYY-MM

    YEAR

    YYYY

<aside> ðŸ’Ą Partitioning, yalnÄązca designated timestamp’a sahip tablolarda mÞmkÞndÞr.

</aside>

Avantajlar

  • Timestamp interval aramalarÄą için azaltÄąlmÄąÅŸ disk IO'su. Bunun nedeni, SQL optimiser’ın partitioningden yararlanmasÄądÄąr.

  • Önemli ÃķlçÞde iyileştirilmiş hesaplamalar ve arama sÞreleri. Bu, Ãķnceki partitionlar için verilerin kronolojisinden ve gÃķreli değişmezliğinden yararlanÄąlarak elde edilir.

  • Veri dosyalarÄąnÄąn fiziksel olarak ayrÄąlmasÄą. Bu, dosya saklama ilkelerini uygulamayÄą veya belirli aralÄąklarÄą Ã§ÄąkarmayÄą kolaylaştÄąrÄąr.

Depolama Örneği

Her partition etkin bir şekilde ana makinede partitioning interval’e karÅŸÄąlÄąk gelen bir directory’dir. Aşağıdaki Ãķrnekte, PARTITION BY MONTH kullanÄąlarak partitionlanmÄąÅŸ bir tablonun gezindiğini varsayÄąyoruz.

[quest-user trips]$ dir
2017-03     2017-10   2018-05     2019-02
2017-04     2017-11   2018-06     2019-03
2017-05     2017-12   2018-07     2019-04
2017-06     2018-01   2018-08   2019-05
2017-07     2018-02   2018-09   2019-06
2017-08     2018-03   2018-10
2017-09     2018-04   2018-11

Diskteki her partition, karÅŸÄąlÄąk gelen timestamp interval’in sÞtun veri dosyalarÄąnÄą içerir.

[quest-user 2019-06]$ dir
_archive    cab_type.v              dropoff_latitude.d     ehail_fee.d
cab_type.d  congestion_surcharge.d  dropoff_location_id.d  extra.d
cab_type.k  dropoff_datetime.d      dropoff_longitude.d    fare_amount.d

Symbol

QuestDB, symbol adÄą verilen bir veri tÞrÞ sunar; tekrarlayan stringleri depolamak için kullanÄąlan bir veri yapÄąsÄą. Internal olarak, symbol tÞrleri bir tamsayÄą tablosu ve bunlara karÅŸÄąlÄąk gelen string değerleri olarak saklanÄąr.

Bu sayfada kavram, isteğe bağlÄą ayar ve symbol tÞrleri için gÃķstergeler sunulmaktadÄąr.

Avantajlar

  • String işlemleri, string yerine int tÞrlerini karÅŸÄąlaştÄąrÄąp yazdığından, sorgu performansÄą bÞyÞk ÃķlçÞde iyileşir.

  • int string tÞrlerine eşlendiğinden, depolama verimliliği bÞyÞk ÃķlçÞde iyileşir.

  • SQL execution, string değerlerinin işlenmesiyle aynÄą sonuca sahip olduğundan kullanÄącÄą için gÃķze batmaz.

  • Ek tablolara veya joinlere olan ihtiyacÄą ortadan kaldÄąrarak veritabanÄą şemalarÄąnÄąn karmaÅŸÄąklığı azalÄąr.

Özellikler

  • Symbol tablolarÄą, sÞtun verilerinden ayrÄą olarak saklanÄąr.

  • Verileri okurken veya yazarken string’den int'a ve tersi yÃķnde hÄązlÄą dÃķnÞşÞm.

  • Symbol tÞrleri olarak tanÄąmlanan sÞtunlar indexing destekler.

  • VarsayÄąlan olarak QuestDB, gelişmiş sorgu hÄązÄą ve ILP alÄąm hÄązÄą için Symbol tÞrlerini bellekte Ãķnbelleğe alÄąr. Ayar yapÄąlandÄąrÄąlabilir.

Örnek

SÞtunlar, diğer tÞrlere benzer şekilde CREATE TABLE kullanÄąlarak Symbol olarak belirtilebilir:

CREATE TABLE my_table
  (symb SYMBOL CAPACITY 128 NOCACHE, price DOUBLE, ts TIMESTAMP)
timestamp(ts);

Aşağıdaki ek symbol ayarlarÄą, sunucu yapÄąlandÄąrmasÄąnÄąn bir parçasÄą olarak genel olarak veya bir tablo oluşturulduğunda local olarak tanÄąmlanÄąr:

  • Symbol kapasitesi: Bu sÞtunun kaç farklÄą değere sahip olmasÄą gerektiğini belirtmek için kullanÄąlan isteğe bağlÄą ayar. KullanÄąlan değere bağlÄą olarak, gerektiğinde QuestDB'nin dÞzgÞn çalÄąÅŸmasÄąna izin vermek için veri yapÄąlarÄą kendilerini yeniden boyutlandÄąracaktÄąr. Symbol değeri sayÄąsÄąnÄąn az girilmesi performans dÞşÞşÞne neden olabilirken, fazla girilmesi daha yÞksek disk alanÄą ve bellek tÞketimi ile sonuçlanabilir. Symbol kapasitesi, cache etkinleştirildiğinde ilk symbol cache boyutunu ayarlamak için de kullanÄąlÄąr.

    • Sunucu genelinde ayar: cairo.default.symbol.capacity, varsayÄąlan 256

    • SÞtun genelinde ayar: CREATE TABLE için CAPACITY seçeneği

  • Cache: Bir symbol’Þn Ãķnbelleğe alÄąnmasÄą gerekip gerekmediğini belirten isteğe bağlÄą ayar. Bir sembol sÞtunu Ãķnbelleğe alÄąndığında, QuestDB, sembol değerlerini ve anahtarlarÄą çÃķzmek için Java heap tabanlÄą bir hash tablosu kullanÄąr. Bir sÞtunda çok sayÄąda farklÄą symbol değeri varsa (Ãķrneğin 100.000'in Þzerinde), heap etkisi Ãķnemli olabilir ve heap boyutuna bağlÄą olarak OutOfMemory hatalarÄąna neden olabilir. Önbelleğe almamak, daha bÞyÞk değer sayÄąmlarÄąyla başa Ã§Äąkabilen ancak daha yavaş olan memory mapped bir yapÄądan yararlanÄąr.

    • Sunucu genelinde ayar: cairo.default.symbol.cache.flag, varsayÄąlan değeri true

    • Bir tablo oluşturulduğunda sÞtun çapÄąnda ayar: CREATE TABLE için CACHE | NOCACHE anahtar sÃķzcÞğÞ


Indexes

Bir index, daha hÄązlÄą okuma erişimi sağlamak için hedef sÞtunun her değeri için satÄąr konumlarÄąnÄą saklar. WHERE koşullu sorgular sÄąrasÄąnda ilgili satÄąrlara doğrudan erişerek tam tablo taramalarÄąnÄą(full table scan) atlamanÄązÄą sağlar.

Symbol sÞtunlarÄą için indeksleme mevcuttur. Diğer tÞrler için index desteği zamanla eklenecektir.

Index oluşturma ve silme

Aşağıdakiler, bir sembol sÞtununu indekslemenin yollarÄądÄąr:

  • CREATE TABLE kullanÄąlarak tablo oluşturma sÄąrasÄąnda

Bir indexi silmek için:

NasÄąl ÇalÄąÅŸÄąr?

Index, hedef symbol için her bir farklÄą değer için bir satÄąr konumlarÄą tablosu oluşturur. Index oluşturulduktan sonra, tabloya veri eklemek indexi gÞncelleyecektir. Indexlenmiş değerler Þzerindeki aramalar, Ãķğelerin bellek konumlarÄąnÄą verecek olan index tablosunda doğrudan gerçekleştirilecek ve bÃķylece gereksiz tablo taramalarÄąndan kaÃ§ÄąnÄąlacaktÄąr.

Tablo Ãķrneği ve dizin tablosu;

Table                                       Index
|Row ID | Symbol    | Value |             | Symbol     | Row IDs       |
| 1     | A         | 1     |             | A          | 1, 2, 4       |
| 2     | A         | 0     |             | B          | 3             |
| 3     | B         | 1     |             | C          | 5             |
| 4     | A         | 1     |
| 5     | C         | 0     |

INSERT INTO Table values(B, 1); biri Tablo için, diğeri Index için olmak Þzere iki gÞncellemeyi tetikler.

Table                                       Index
|Row ID | Symbol    | Value |             | Symbol     | Row IDs       |
| 1     | A         | 1     |             | A          | 1, 2, 4       |
| 2     | A         | 0     |             | B          | 3, 6          |
| 3     | B         | 1     |             | C          | 5             |
| 4     | A         | 1     |
| 5     | C         | 0     |
| 6     | B         | 1     |

Index capacity

Bir symbol sÞtunu indexe eklendiğinde, diskteki tek bir depolama bloğunda kaç satÄąr id’nin depolanacağınÄą belirtmek için ek bir index kapasitesi tanÄąmlanabilir:

  • Sunucu genelinde ayar: cairo.index.value.block.size, varsayÄąlan değeri 256

SatÄąr id’lerini depolamak için kullanÄąlan daha az blok, daha iyi performans sağlar. AynÄą zamanda ayarÄąn gereğinden fazla boyutlandÄąrÄąlmasÄą, gerekenden daha yÞksek disk alanÄą kullanÄąmÄąna neden olacaktÄąr.

Avantajlar

Index, genellikle WHERE yan tÞmceleri kullanÄąrken, indexe alÄąnmÄąÅŸ bir sÞtunun bir alt kÞmesini kapsayan sorgularÄąn karmaÅŸÄąklığınÄą bÞyÞk ÃķlçÞde azaltmanÄąza olanak tanÄąr.

YukarÄądaki tabloya uygulanan aşağıdaki sorguyu gÃķz ÃķnÞnde bulundurun SELECT sum(Value) FROM Table WHERE Symbol='A';

  • Index olmadan, sorgu engine’i, sorguyu gerçekleştirmek için tÞm tabloyu tarayacaktÄąr. 6 işlem yapmasÄą gerekecek (6 satÄąrÄąn her birini bir kez okuyacak).

  • Index ile, sorgu engine’i Ãķnce, oldukça kÞçÞk olan indeks tablosunu tarar. Örneğimizde, ilk satÄąrda A'yÄą bulacaktÄąr. ArdÄąndan, sorgu engine’i, karÅŸÄąlÄąk gelen değerleri okumak için tablodaki 1, 2, 4 numaralÄą belirli konumlardaki değerleri kontrol eder. Sonuç olarak, tablodaki yalnÄązca ilgili satÄąrlarÄą tarar ve alakasÄąz satÄąrlara dokunmaz.

Trade-offs

  • Depolama alanÄą: Index, her bir farklÄą symbol değerini ve bu symbollerin bulunabileceği konumlarÄą içeren bir tablo tutacaktÄąr. Sonuç olarak, bir symbol alanÄąnÄą indekslemeyle ilişkili kÞçÞk bir depolama maliyeti vardÄąr.

  • Ingestion(alÄąm) performansÄą: Tablodaki her yeni giriş, Index tablosunda bir girişi tetikler. Bu, herhangi bir yazmanÄąn artÄąk iki yazma işlemi gerektireceği ve dolayÄąsÄąyla iki kat daha uzun sÞreceği anlamÄąna gelir.

Index capacity

Zaman içinde 200 unique hisse senedi symbol’Þ ve 1.000.000.000 kayÄąt içeren Ãķrnek bir tablo dÞşÞnÞn. Index, her sembol için 1.000.000.000 / 200 satÄąr id’si, yani symbol baÅŸÄąna 5.000.000 depolamalÄądÄąr.

  • Bu durumda index kapasitesi 1.048.576 olarak ayarlanÄąrsa, QuestDB satÄąr id’lerini depolamak için 5 blok kullanÄąr.

  • Bu durumda index kapasitesi 1.024 olarak ayarlanÄąrsa blok sayÄąsÄą 4.883 olacaktÄąr.

işlemi sÄąrasÄąnda

işlemi sÄąrasÄąnda (dynamic timestamp)

yoluyla veri alÄąnÄąrken, QuestDB'de zaten mevcut olmayan tablolar için, partitionlar varsayÄąlan olarak bir timestamp sÞtunuyla gÞne gÃķre otomatik olarak uygulanÄąr

Zaman damgasÄą aramasÄą, >, <= vb. gibi normal işleçlerle gerçekleştirilebilir. Ancak, QuestDB, daha hÄązlÄą ve daha az ayrÄąntÄąlÄą olan sağlar.

yoluyla CREATE TABLE ve PARTITION BY DAY kullanÄąlÄąrken varsayÄąlan davranÄąÅŸ PARTITION BY NONE şeklindedir.

Partitionlar tablo oluşturulurken tanÄąmlanÄąr. Daha fazla bilgi için bÃķlÞmÞne bakÄąn.

Mevcut bir symbol sÞtununu indekslemek için kullanma

â€Ē

SÞtun genelinde ayar: CREATE TABLE için seçeneği

SÞtun genelinde ayar:

📜
CREATE TABLE
SELECT
ILP
native bir notasyon
ILP ingestion
CREATE TABLE
ALTER TABLE ALTER COLUMN ADD INDEX
ALTER TABLE ALTER COLUMN DROP INDEX
index
ALTER TABLE COLUMN ADD INDEX