Karakteristik lang Q ak KDB+ lè l sèvi avèk egzanp yon sèvis an tan reyèl

Ou ka li sou kisa baz KDB+ la, langaj pwogram Q a ye, ki sa fòs ak feblès yo ye nan anvan mwen an. Atik ak yon ti tan nan entwodiksyon an. Nan atik la, nou pral aplike yon sèvis sou Q ki pral trete kouran done fèk ap rantre ak kalkile divès fonksyon agrégasyon chak minit nan mòd "tan reyèl" (sa vle di, li pral gen tan kalkile tout bagay anvan pwochen pòsyon nan done). Karakteristik prensipal Q a se ke li se yon lang vektè ki pèmèt ou opere pa ak objè sèl, men ak etalaj yo, etalaj yo ak lòt objè konplèks. Lang tankou Q ak fanmi li yo K, J, APL yo pi popilè pou konsizyon yo. Souvan, yon pwogram ki pran plizyè ekran kòd nan yon lang abitye tankou Java ka ekri sou yo nan kèk liy. Sa a se sa mwen vle demontre nan atik sa a.

Karakteristik lang Q ak KDB+ lè l sèvi avèk egzanp yon sèvis an tan reyèl

Entwodiksyon

KDB+ se yon baz done kolon ki konsantre sou gwo kantite done, kòmande nan yon fason espesifik (premyèman pa tan). Li se itilize prensipalman nan enstitisyon finansye - bank, fon envestisman, konpayi asirans. Lang Q a se lang entèn KDB+ ki pèmèt ou travay byen ak done sa yo. Ideoloji Q a se konsizyon ak efikasite, pandan y ap sakrifis klè. Sa a jistifye pa lefèt ke lang vektè a pral difisil pou konprann nan nenpòt ka, ak konsizyon ak richès nan anrejistreman an pèmèt ou wè yon pati pi gwo nan pwogram nan sou yon ekran, ki finalman fè li pi fasil yo konprann.

Nan atik sa a nou aplike yon pwogram plen véritable nan Q epi ou ta ka vle eseye li. Pou fè sa, w ap bezwen aktyèl Q a. Ou ka telechaje gratis vèsyon an 32-bit sou sit entènèt konpayi kx la - www.kx.com. La, si w enterese, w ap jwenn enfòmasyon referans sou Q, liv la Q Pou mòtèl ak plizyè atik sou sijè sa a.

Deklarasyon sou pwoblèm nan

Gen yon sous ki voye yon tab ak done chak 25 milisgond. Depi KDB + yo itilize prensipalman nan finans, nou pral asime ke sa a se yon tablo tranzaksyon (komès), ki gen kolòn sa yo: tan (tan an milisgond), sym (deziyasyon konpayi sou echanj la - IBM, AAPL,…), pri (pri a nan ki aksyon yo te achte), gwosè (gwosè tranzaksyon an). Entèval 25 milisgond lan abitrè, pa twò piti epi li pa twò long. Prezans li vle di ke done yo vini nan sèvis la deja tampon. Li ta fasil aplike tanpon sou bò sèvis la, ki gen ladan tampon dinamik depann sou chaj aktyèl la, men pou senplisite, nou pral konsantre sou yon entèval fiks.

Sèvis la dwe konte chak minit pou chak senbòl k ap rantre nan kolòn sym nan yon seri fonksyon total - pri max, pri mwayèn, gwosè sòm, elatriye. enfòmasyon itil. Pou senplisite, nou pral asime ke tout fonksyon yo ka kalkile incrémentielle, i.e. pou jwenn yon nouvo valè, li se ase konnen de nimewo - ansyen ak valè yo fèk ap rantre. Pa egzanp, fonksyon max, mwayèn, sòm gen pwopriyete sa a, men fonksyon medyàn lan pa genyen.

Nou pral sipoze tou ke kouran done fèk ap rantre a se tan òdone. Sa ap ban nou opòtinite pou travay sèlman ak dènye minit. Nan pratik, li ase pou kapab travay ak minit aktyèl yo ak anvan yo nan ka kèk mizajou yo an reta. Pou senplisite, nou pa pral konsidere ka sa a.

Fonksyon agrégation

Fonksyon agrégasyon obligatwa yo endike anba a. Mwen te pran kòm anpil nan yo ke posib ogmante chaj la sou sèvis la:

  • segondè - pri maksimòm - pri maksimòm pou chak minit.
  • ba - pri min - pri minimòm pou chak minit.
  • firstPrice – premye pri – premye pri pou chak minit.
  • lastPrice – dènye pri – dènye pri pou chak minit.
  • firstSize - premye gwosè - premye gwosè komès pou chak minit.
  • lastSize - dènye gwosè - dènye gwosè komès nan yon minit.
  • numTrades – konte i – kantite echanj pa minit.
  • volim - gwosè sòm - sòm gwosè komès pou chak minit.
  • pvolume - pri sòm - sòm pri pou chak minit, obligatwa pou avgPrice.
  • – pri woulman sòm * gwosè – volim total tranzaksyon pou chak minit.
  • avgPrice – pvolume%numTrades – pri mwayèn pou chak minit.
  • avgSize – volim%numTrades – gwosè komès mwayèn pou chak minit.
  • vwap - woulman% volim - pri mwayèn pou chak minit filaplon selon gwosè tranzaksyon an.
  • cumVolume - volim sòm - akimile gwosè tranzaksyon yo pandan tout tan an.

Se pou nou imedyatman diskite sou yon pwen ki pa evidan - ki jan yo inisyalize kolòn sa yo pou premye fwa ak pou chak minit ki vin apre. Gen kèk kolòn nan kalite firstPrice dwe inisyalize nan nil chak fwa valè yo pa defini. Lòt kalite volim yo dwe toujou mete sou 0. Genyen tou kolòn ki mande pou yon apwòch konbine - pou egzanp, cumVolume dwe kopye nan minit anvan an, epi pou premye a mete a 0. Ann mete tout paramèt sa yo lè l sèvi avèk done diksyonè a. kalite (analòg ak yon dosye):

// list ! list – создать словарь, 0n – float null, 0N – long null, `sym – тип символ, `sym1`sym2 – список символов
initWith:`sym`time`high`low`firstPrice`lastPrice`firstSize`lastSize`numTrades`volume`pvolume`turnover`avgPrice`avgSize`vwap`cumVolume!(`;00:00;0n;0n;0n;0n;0N;0N;0;0;0.0;0.0;0n;0n;0n;0);
aggCols:reverse key[initWith] except `sym`time; // список всех вычисляемых колонок, reverse объяснен ниже

Mwen te ajoute sym ak tan nan diksyonè a pou konvenyans, kounye a initWith se yon liy ki pare soti nan tablo total final la, kote li rete yo mete sym ki kòrèk la ak tan. Ou ka itilize li pou ajoute nouvo ranje nan yon tab.

Nou pral bezwen aggCols lè nou kreye yon fonksyon agrégation. Lis la dwe ranvèse akòz lòd ekspresyon nan Q yo evalye (de bò dwat a goch). Objektif la se asire kalkil la ale soti nan wo a cumVolume, paske kèk kolòn depann de kolòn anvan yo.

Kolòn ki bezwen kopye nan yon nouvo minit soti nan premye a, yo ajoute kolòn sym pou konvenyans:

rollColumns:`sym`cumVolume;

Koulye a, ann divize kolòn yo an gwoup dapre jan yo ta dwe mete ajou. Twa kalite yo ka distenge:

  1. Akimilatè (volim, woulman, ..) - nou dwe ajoute valè a fèk ap rantre nan yon sèl anvan an.
  2. Avèk yon pwen espesyal (segondè, ba, ..) - premye valè a nan minit la pran nan done yo fèk ap rantre, rès la yo kalkile lè l sèvi avèk fonksyon an.
  3. Repoze. Toujou kalkile lè l sèvi avèk yon fonksyon.

Ann defini varyab pou klas sa yo:

accumulatorCols:`numTrades`volume`pvolume`turnover;
specialCols:`high`low`firstPrice`firstSize;

Lòd kalkil

Nou pral mete ajou tablo total la nan de etap. Pou efikasite, nou premye retresi tab la fèk ap rantre pou gen yon sèl ranje pou chak karaktè ak minit. Lefèt ke tout fonksyon nou yo se incrémentielle ak asosyasyon garanti ke rezilta a nan etap adisyonèl sa a pa pral chanje. Ou ta ka retresi tab la lè l sèvi avèk chwazi:

select high:max price, low:min price … by sym,time.minute from table

Metòd sa a gen yon dezavantaj - seri kolòn kalkile yo predefini. Erezman, nan Q, seleksyon an aplike tou kòm yon fonksyon kote ou ka ranplase agiman ki te kreye dinamik:

?[table;whereClause;byClause;selectClause]

Mwen pa pral dekri an detay fòma agiman yo nan ka nou an, sèlman pa ak ekspresyon chwazi yo pral non trivial epi yo ta dwe diksyonè nan fòm kolòn yo! Kidonk, fonksyon rediksyon an ka defini jan sa a:

selExpression:`high`low`firstPrice`lastPrice`firstSize`lastSize`numTrades`volume`pvolume`turnover!parse each ("max price";"min price";"first price";"last price";"first size";"last size";"count i";"sum size";"sum price";"sum price*size"); // each это функция map в Q для одного списка
preprocess:?[;();`sym`time!`sym`time.minute;selExpression];

Pou klè, mwen te itilize fonksyon an analiz, ki vire yon fisèl ak yon ekspresyon Q nan yon valè ki ka pase nan fonksyon an eval epi ki obligatwa nan seleksyon an fonksyon. Epitou sonje ke preprosesis defini kòm yon pwojeksyon (sa vle di, yon fonksyon ak agiman pasyèlman defini) nan fonksyon an chwazi, yon agiman (tablo a) ki manke. Si nou aplike preprocess nan yon tab, nou pral jwenn yon tab konprese.

Dezyèm etap la se mete ajou tablo total la. Ann premye ekri algorithm la nan pseudocode:

for each sym in inputTable
  idx: row index in agg table for sym+currentTime;
  aggTable[idx;`high]: aggTable[idx;`high] | inputTable[sym;`high];
  aggTable[idx;`volume]: aggTable[idx;`volume] + inputTable[sym;`volume];
  …

Nan Q, li komen pou itilize kat/diminye fonksyon olye de boucles. Men, kòm Q se yon lang vektè epi nou ka fasilman aplike tout operasyon yo nan tout senbòl nan yon fwa, Lè sa a, nan yon premye apwoksimasyon nou ka fè san yo pa yon bouk ditou, fè operasyon sou tout senbòl nan yon fwa:

idx:calcIdx inputTable;
row:aggTable idx;
aggTable[idx;`high]: row[`high] | inputTable`high;
aggTable[idx;`volume]: row[`volume] + inputTable`volume;
…

Men, nou ka ale pi lwen, Q gen yon operatè inik ak trè pwisan - operatè a plasman jeneralize. Li pèmèt ou chanje yon seri valè nan yon estrikti done konplèks lè l sèvi avèk yon lis endis, fonksyon ak agiman. Nan ka nou an, li sanble sa a:

idx:calcIdx inputTable;
rows:aggTable idx;
// .[target;(idx0;idx1;..);function;argument] ~ target[idx 0;idx 1;…]: function[target[idx 0;idx 1;…];argument], в нашем случае функция – это присваивание
.[aggTable;(idx;aggCols);:;flip (row[`high] | inputTable`high;row[`volume] + inputTable`volume;…)];

Malerezman, pou plase nan yon tab ou bezwen yon lis ranje, pa kolòn, epi ou gen transpose matris la (lis kolòn nan lis ranje) lè l sèvi avèk fonksyon an baskile. Sa a se chè pou yon tab gwo, kidonk olye nou aplike yon plasman jeneralize nan chak kolòn separeman, lè l sèvi avèk fonksyon kat jeyografik la (ki sanble ak yon apòt):

.[aggTable;;:;]'[(idx;)each aggCols; (row[`high] | inputTable`high;row[`volume] + inputTable`volume;…)];

Nou itilize ankò fonksyon pwojeksyon. Epitou sonje ke nan Q, kreye yon lis se tou yon fonksyon epi nou ka rele li lè l sèvi avèk chak (kat) fonksyon an pou jwenn yon lis lis.

Pou asire ke seri a nan kolòn kalkile pa fiks, nou pral kreye ekspresyon ki anwo a dinamik. Se pou premye defini fonksyon yo kalkile chak kolòn, lè l sèvi avèk ranje a ak varyab inp pou fè referans a done total ak antre:

aggExpression:`high`low`firstPrice`lastPrice`firstSize`lastSize`avgPrice`avgSize`vwap`cumVolume!
 ("row[`high]|inp`high";"row[`low]&inp`low";"row`firstPrice";"inp`lastPrice";"row`firstSize";"inp`lastSize";"pvolume%numTrades";"volume%numTrades";"turnover%volume";"row[`cumVolume]+inp`volume");

Gen kèk kolòn espesyal yo pa ta dwe kalkile premye valè yo. Nou ka detèmine ke li se premye a pa kolòn ranje [`numTrades] - si li gen 0, Lè sa a, valè a se premye. Q gen yon fonksyon chwazi - ?[Boolean list;list1;list2] - ki chwazi yon valè nan lis 1 oswa 2 selon kondisyon ki nan premye agiman an:

// high -> ?[isFirst;inp`high;row[`high]|inp`high]
// @ - тоже обобщенное присваивание для случая когда индекс неглубокий
@[`aggExpression;specialCols;{[x;y]"?[isFirst;inp`",y,";",x,"]"};string specialCols];

Isit la mwen te rele yon plasman jeneralize ak fonksyon mwen an (yon ekspresyon nan aparèy òtopedik boukle). Li resevwa valè aktyèl la (premye agiman an) ak yon agiman adisyonèl, ke mwen pase nan 4yèm paramèt la.

Ann ajoute moun kap pale batri separeman, paske fonksyon an se menm pou yo:

// volume -> row[`volume]+inp`volume
aggExpression[accumulatorCols]:{"row[`",x,"]+inp`",x } each string accumulatorCols;

Sa a se yon plasman nòmal pa estanda Q, men mwen bay yon lis valè nan yon fwa. Finalman, ann kreye fonksyon prensipal la:

// ":",/:aggExprs ~ map[{":",x};aggExpr] => ":row[`high]|inp`high" присвоим вычисленное значение переменной, потому что некоторые колонки зависят от уже вычисленных значений
// string[cols],'exprs ~ map[,;string[cols];exprs] => "high:row[`high]|inp`high" завершим создание присваивания. ,’ расшифровывается как map[concat]
// ";" sv exprs – String from Vector (sv), соединяет список строк вставляя “;” посредине
updateAgg:value "{[aggTable;idx;inp] row:aggTable idx; isFirst_0=row`numTrades; .[aggTable;;:;]'[(idx;)each aggCols;(",(";"sv string[aggCols],'":",/:aggExpression aggCols),")]}";

Avèk ekspresyon sa a, mwen dinamik kreye yon fonksyon nan yon fisèl ki gen ekspresyon mwen te bay pi wo a. Rezilta a pral sanble tankou sa a:

{[aggTable;idx;inp] rows:aggTable idx; isFirst_0=row`numTrades; .[aggTable;;:;]'[(idx;)each aggCols ;(cumVolume:row[`cumVolume]+inp`cumVolume;… ; high:?[isFirst;inp`high;row[`high]|inp`high])]}

Lòd evalyasyon kolòn nan envèse paske nan Q lòd evalyasyon an se de dwat a goch.

Koulye a, nou gen de fonksyon prensipal ki nesesè pou kalkil, nou jis bezwen ajoute yon ti enfrastrikti ak sèvis la pare.

Etap final yo

Nou gen fonksyon preprocess ak updateAgg ki fè tout travay la. Men, li toujou nesesè asire tranzisyon ki kòrèk la nan minit ak kalkile endèks pou agrégation. Premye a tout, ann defini fonksyon init la:

init:{
  tradeAgg:: 0#enlist[initWith]; // создаем пустую типизированную таблицу, enlist превращает словарь в таблицу, а 0# означает взять 0 элементов из нее
  currTime::00:00; // начнем с 0, :: означает, что присваивание в глобальную переменную
  currSyms::`u#`symbol$(); // `u# - превращает список в дерево, для ускорения поиска элементов
  offset::0; // индекс в tradeAgg, где начинается текущая минута 
  rollCache:: `sym xkey update `u#sym from rollColumns#tradeAgg; // кэш для последних значений roll колонок, таблица с ключом sym
 }

Nou pral defini tou fonksyon woulo liv la, ki pral chanje minit aktyèl la:

roll:{[tm]
  if[currTime>tm; :init[]]; // если перевалили за полночь, то просто вызовем init
  rollCache,::offset _ rollColumns#tradeAgg; // обновим кэш – взять roll колонки из aggTable, обрезать, вставить в rollCache
  offset::count tradeAgg;
  currSyms::`u#`$();
 }

Nou pral bezwen yon fonksyon pou ajoute nouvo karaktè:

addSyms:{[syms]
  currSyms,::syms; // добавим в список известных
  // добавим в таблицу sym, time и rollColumns воспользовавшись обобщенным присваиванием.
  // Функция ^ подставляет значения по умолчанию для roll колонок, если символа нет в кэше. value flip table возвращает список колонок в таблице.
  `tradeAgg upsert @[count[syms]#enlist initWith;`sym`time,cols rc;:;(syms;currTime), (initWith cols rc)^value flip rc:rollCache ([] sym: syms)];
 }

Epi finalman, fonksyon upd (non tradisyonèl pou fonksyon sa a pou sèvis Q), kliyan an rele pou ajoute done:

upd:{[tblName;data] // tblName нам не нужно, но обычно сервис обрабатывает несколько таблиц 
  tm:exec distinct time from data:() xkey preprocess data; // preprocess & calc time
  updMinute[data] each tm; // добавим данные для каждой минуты
};
updMinute:{[data;tm]
  if[tm<>currTime; roll tm; currTime::tm]; // поменяем минуту, если необходимо
  data:select from data where time=tm; // фильтрация
  if[count msyms:syms where not (syms:data`sym)in currSyms; addSyms msyms]; // новые символы
  updateAgg[`tradeAgg;offset+currSyms?syms;data]; // обновим агрегированную таблицу. Функция ? ищет индекс элементов списка справа в списке слева.
 };

Se tout. Men kòd konplè sèvis nou an, jan yo te pwomèt la, jis kèk liy:

initWith:`sym`time`high`low`firstPrice`lastPrice`firstSize`lastSize`numTrades`volume`pvolume`turnover`avgPrice`avgSize`vwap`cumVolume!(`;00:00;0n;0n;0n;0n;0N;0N;0;0;0.0;0.0;0n;0n;0n;0);
aggCols:reverse key[initWith] except `sym`time;
rollColumns:`sym`cumVolume;

accumulatorCols:`numTrades`volume`pvolume`turnover;
specialCols:`high`low`firstPrice`firstSize;

selExpression:`high`low`firstPrice`lastPrice`firstSize`lastSize`numTrades`volume`pvolume`turnover!parse each ("max price";"min price";"first price";"last price";"first size";"last size";"count i";"sum size";"sum price";"sum price*size");
preprocess:?[;();`sym`time!`sym`time.minute;selExpression];

aggExpression:`high`low`firstPrice`lastPrice`firstSize`lastSize`avgPrice`avgSize`vwap`cumVolume!("row[`high]|inp`high";"row[`low]&inp`low";"row`firstPrice";"inp`lastPrice";"row`firstSize";"inp`lastSize";"pvolume%numTrades";"volume%numTrades";"turnover%volume";"row[`cumVolume]+inp`volume");
@[`aggExpression;specialCols;{"?[isFirst;inp`",y,";",x,"]"};string specialCols];
aggExpression[accumulatorCols]:{"row[`",x,"]+inp`",x } each string accumulatorCols;
updateAgg:value "{[aggTable;idx;inp] row:aggTable idx; isFirst_0=row`numTrades; .[aggTable;;:;]'[(idx;)each aggCols;(",(";"sv string[aggCols],'":",/:aggExpression aggCols),")]}"; / '

init:{
  tradeAgg::0#enlist[initWith];
  currTime::00:00;
  currSyms::`u#`symbol$();
  offset::0;
  rollCache:: `sym xkey update `u#sym from rollColumns#tradeAgg;
 };
roll:{[tm]
  if[currTime>tm; :init[]];
  rollCache,::offset _ rollColumns#tradeAgg;
  offset::count tradeAgg;
  currSyms::`u#`$();
 };
addSyms:{[syms]
  currSyms,::syms;
  `tradeAgg upsert @[count[syms]#enlist initWith;`sym`time,cols rc;:;(syms;currTime),(initWith cols rc)^value flip rc:rollCache ([] sym: syms)];
 };

upd:{[tblName;data] updMinute[data] each exec distinct time from data:() xkey preprocess data};
updMinute:{[data;tm]
  if[tm<>currTime; roll tm; currTime::tm];
  data:select from data where time=tm;
  if[count msyms:syms where not (syms:data`sym)in currSyms; addSyms msyms];
  updateAgg[`tradeAgg;offset+currSyms?syms;data];
 };

Tès

Ann tcheke pèfòmans sèvis la. Pou fè sa, ann kouri li nan yon pwosesis separe (mete kòd la nan fichye service.q la) epi rele fonksyon init la:

q service.q –p 5566

q)init[]

Nan yon lòt konsole, kòmanse dezyèm pwosesis Q a epi konekte ak premye a:

h:hopen `:host:5566
h:hopen 5566 // если оба на одном хосте

Premyèman, ann kreye yon lis senbòl - 10000 moso epi ajoute yon fonksyon pou kreye yon tab o aza. Nan dezyèm konsole a:

syms:`IBM`AAPL`GOOG,-9997?`8
rnd:{[n;t] ([] sym:n?syms; time:t+asc n#til 25; price:n?10f; size:n?10)}

Mwen te ajoute twa senbòl reyèl nan lis la pou fè li pi fasil pou chèche yo nan tablo a. Fonksyon rnd kreye yon tab o aza ak n ranje, kote tan an varye ant t rive t+25 milisgond.

Koulye a, ou ka eseye voye done nan sèvis la (ajoute premye dis èdtan yo):

{h (`upd;`trade;rnd[10000;x])} each `time$00:00 + til 60*10

Ou ka tcheke nan sèvis la ke yo te mete ajou tab la:

c 25 200
select from tradeAgg where sym=`AAPL
-20#select from tradeAgg where sym=`AAPL

Rezilta:

sym|time|high|low|firstPrice|lastPrice|firstSize|lastSize|numTrades|volume|pvolume|turnover|avgPrice|avgSize|vwap|cumVolume
--|--|--|--|--|--------------------------------
AAPL|09:27|9.258904|9.258904|9.258904|9.258904|8|8|1|8|9.258904|74.07123|9.258904|8|9.258904|2888
AAPL|09:28|9.068162|9.068162|9.068162|9.068162|7|7|1|7|9.068162|63.47713|9.068162|7|9.068162|2895
AAPL|09:31|4.680449|0.2011121|1.620827|0.2011121|1|5|4|14|9.569556|36.84342|2.392389|3.5|2.631673|2909
AAPL|09:33|2.812535|2.812535|2.812535|2.812535|6|6|1|6|2.812535|16.87521|2.812535|6|2.812535|2915
AAPL|09:34|5.099025|5.099025|5.099025|5.099025|4|4|1|4|5.099025|20.3961|5.099025|4|5.099025|2919

Koulye a, ann fè tès chaj pou chèche konnen ki kantite done sèvis la ka trete pou chak minit. Kite m 'fè ou sonje ke nou mete entèval aktyalizasyon a 25 milisgond. An konsekans, sèvis la dwe (an mwayèn) anfòm nan omwen 20 milisgond pou chak aktyalizasyon pou bay itilizatè yo tan pou mande done. Antre sa ki annapre yo nan dezyèm pwosesis la:

tm:10:00:00.000
stressTest:{[n] 1 string[tm]," "; times,::h ({st:.z.T; upd[`trade;x]; .z.T-st};rnd[n;tm]); tm+:25}
start:{[n] times::(); do[4800;stressTest[n]]; -1 " "; `min`avg`med`max!(min times;avg times;med times;max times)}

4800 se de minit. Ou ka eseye kouri an premye pou 1000 ranje chak 25 milisgond:

start 1000

Nan ka mwen an, rezilta a se alantou yon koup la milisgond pou chak aktyalizasyon. Se konsa, mwen pral imedyatman ogmante kantite ranje a 10.000:

start 10000

Rezilta:

min| 00:00:00.004
avg| 9.191458
med| 9f
max| 00:00:00.030

Ankò, pa gen anyen espesyal, men sa a se 24 milyon liy pou chak minit, 400 mil pou chak segonn. Pou plis pase 25 milisgond, aktyalizasyon a ralanti sèlman 5 fwa, aparamman lè minit nan chanje. Ann ogmante a 100.000:

start 100000

Rezilta:

min| 00:00:00.013
avg| 25.11083
med| 24f
max| 00:00:00.108
q)sum times
00:02:00.532

Kòm ou ka wè, sèvis la ka apèn fè fas, men kanmenm li jere yo rete ap flote. Tankou yon volim nan done (240 milyon ranje pou chak minit) trè gwo nan ka sa yo, li komen yo lanse plizyè klon (oswa plizyè douzèn klon) nan sèvis la, chak nan yo ki trete sèlman yon pati nan karaktè yo. Toujou, rezilta a se enpresyonan pou yon lang entèprete ki konsantre prensipalman sou depo done.

Kesyon an ka leve sou poukisa tan ap grandi ki pa lineyè ak gwosè a nan chak aktyalizasyon. Rezon ki fè la se ke fonksyon an retresi se aktyèlman yon fonksyon C, ki se pi plis efikas pase updateAgg. Kòmanse soti nan yon sèten gwosè aktyalizasyon (apeprè 10.000), updateAgg rive nan plafon li yo ak Lè sa a, tan ekzekisyon li yo pa depann de gwosè aktyalizasyon an. Li se akòz etap preliminè Q ke sèvis la kapab dijere volim done sa yo. Sa a mete aksan sou ki jan li enpòtan yo chwazi algorithm nan dwa lè w ap travay ak done gwo. Yon lòt pwen se depo kòrèk done nan memwa. Si done yo pa te estoke kolon oswa yo pa te bay lòd pa tan, Lè sa a, nou ta vin abitye ak yon bagay tankou yon miss kachèt TLB - absans la nan yon adrès paj memwa nan kachèt adrès processeur la. Chèche yon adrès pran apeprè 30 fwa plis si li pa reyisi, epi si done yo gaye, li ka ralanti sèvis la plizyè fwa.

Konklizyon

Nan atik sa a, mwen te montre ke baz done KDB + ak Q yo apwopriye pa sèlman pou estoke gwo done ak aksè fasil nan seleksyon an, men tou pou kreye sèvis tretman done ki kapab dijere dè santèn de milyon ranje / jigokte done menm nan yon sèl pwosesis Q. Lang Q nan tèt li pèmèt pou aplikasyon trè kout ak efikas nan algoritm ki gen rapò ak pwosesis done akòz nati vektè li yo, bati nan entèprèt dyalèk SQL ak yon seri fonksyon bibliyotèk ki gen anpil siksè.

Mwen pral sonje ke pi wo a se jis yon pati nan sa Q ka fè, li gen lòt karakteristik inik tou. Pou egzanp, yon pwotokòl IPC trè senp ki efase fwontyè ki genyen ant pwosesis Q endividyèl ak pèmèt ou konbine dè santèn de pwosesis sa yo nan yon rezo sèl, ki ka lokalize sou plizyè douzèn serveurs nan diferan pati nan mond lan.

Sous: www.habr.com

Achte hosting serye pou sit ki gen pwoteksyon DDoS, sèvè VPS VDS 🔥 Achte yon hébergement sit entènèt serye ak pwoteksyon DDoS, sèvè VPS VDS | ProHoster