QuestDB (TR)
03/02/2023
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:
CREATE TABLE
iÅlemi sÄąrasÄąndaSELECT
iÅlemi sÄąrasÄąnda (dynamic timestamp)ILP 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
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
Zaman damgasÄą aramasÄą, >
, <=
vb. gibi normal iÅleçlerle gerçekleÅtirilebilir. Ancak, QuestDB, daha hÄązlÄą ve daha az ayrÄąntÄąlÄą olan native bir notasyon saÄlar.
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 intervalleri
NONE
,YEAR
,MONTH
,DAY
, veHOUR
âdur.ILP ingestion yoluyla
CREATE TABLE
vePARTITION BY DAY
kullanÄąlÄąrken varsayÄąlan davranÄąÅPARTITION BY NONE
Åeklindedir.Partitionlar tablo oluÅturulurken tanÄąmlanÄąr. Daha fazla bilgi için
CREATE TABLE
bÃķlÞmÞne bakÄąn.Partition dizinleri(directory) için adlandÄąrma kuralÄą aÅaÄÄądaki gibidir:
Table PartitionPartition formatHOUR
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
yerineint
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
âdenint
'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Äąlan256
SÞtun genelinde ayar:
CREATE TABLE
içinCAPACITY
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Äą olarakOutOfMemory
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Äeritrue
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ÄąndaMevcut bir symbol sÞtununu indekslemek için
ALTER TABLE ALTER COLUMN ADD INDEX
kullanma
Bir indexi silmek için:
âĒ ALTER TABLE ALTER COLUMN DROP INDEX
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Äeri256
SÞtun genelinde ayar:
CREATE TABLE
içinindex
seçeneÄiSÞtun genelinde ayar: ALTER TABLE COLUMN ADD INDEX
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.
Last updated
Was this helpful?