{"id":75530,"date":"2020-03-26T19:42:23","date_gmt":"2020-03-26T17:42:23","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/vyvod-rezultatov-poiska-i-problemy-s-proizvoditelnostyu"},"modified":"2020-03-26T19:42:23","modified_gmt":"2020-03-26T17:42:23","slug":"vyvod-rezultatov-poiska-i-problemy-s-proizvoditelnostyu","status":"publish","type":"post","link":"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/vyvod-rezultatov-poiska-i-problemy-s-proizvoditelnostyu","title":{"rendered":"V\u00fdstup v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Jedn\u00fdm z typick\u00fdch scen\u00e1rov vo v\u0161etk\u00fdch be\u017en\u00fdch aplik\u00e1ci\u00e1ch je vyh\u013ead\u00e1vanie \u00fadajov pod\u013ea ur\u010dit\u00fdch krit\u00e9ri\u00ed a ich zobrazenie v \u013eahko \u010ditate\u013enej forme. M\u00f4\u017eu tu by\u0165 aj \u010fal\u0161ie mo\u017enosti, ako je triedenie, skupinovanie a str\u00e1nkovanie. \u00daloha je v z\u00e1sade trivi\u00e1lna, av\u0161ak pri jej rie\u0161en\u00ed mnoh\u00ed v\u00fdvoj\u00e1ri robia mno\u017estvo ch\u00fdb, ktor\u00e9 n\u00e1sledne ovplyv\u0148uj\u00fa v\u00fdkon. Pok\u00fasime sa presk\u00fama\u0165 r\u00f4zne varianty rie\u0161enia tejto \u00falohy a formulova\u0165 odpor\u00fa\u010dania na v\u00fdber najefekt\u00edvnej\u0161ej implement\u00e1cie.<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdstup v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom.\" src=\"\/wp-content\/uploads\/2020\/03\/364ab29c4a6117ff441b933a38ec8401.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Variant str\u00e1nkovania #1<\/h2>\n<p>\nNajjednoduch\u0161\u00ed variant, ktor\u00fd napadne na prv\u00fd poh\u013ead, je str\u00e1nkovanie v\u00fdsledkov vyh\u013ead\u00e1vania v jeho najklasickej\u0161ej podobe.<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdstup v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom.\" src=\"\/wp-content\/uploads\/2020\/03\/4957d9ad21a8a0c70390b224fe76cb33.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nPredpokladajme, \u017ee v aplik\u00e1cii sa pou\u017e\u00edva rela\u010dn\u00e1 datab\u00e1za. V tomto pr\u00edpade na zobrazenie inform\u00e1ci\u00ed v takto form\u00e1te bude potrebn\u00e9 vykona\u0165 dva SQL dotazy:<\/p>\n<ul>\n<li>Z\u00edska\u0165 riadky pre aktu\u00e1lnu str\u00e1nku.<\/li>\n<li>Vypo\u010d\u00edta\u0165 celkov\u00fd po\u010det riadkov, ktor\u00e9 sp\u013a\u0148aj\u00fa vyh\u013ead\u00e1vacie krit\u00e9ri\u00e1 \u2014 to je potrebn\u00e9 na zobrazenie str\u00e1nok.<\/li>\n<\/ul>\n<p>\nPozrime sa na prv\u00fd dotaz na pr\u00edklade testovacej MS SQL datab\u00e1zy <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Microsoft\/sql-server-samples\/releases\/download\/adventureworks\/AdventureWorks2016_EXT.bak\">AdventureWorks <\/a><\/noindex>pre server 2016. Na tento \u00fa\u010del pou\u017eijeme tabu\u013eku Sales.SalesOrderHeader:<\/p>\n<pre><code class=\"sql\">SELECT * FROM Sales.SalesOrderHeader\nORDER BY OrderDate DESC\nOFFSET 0 ROWS\nFETCH NEXT 50 ROWS ONLY\n<\/code><\/pre>\n<p>\nUveden\u00fd dotaz vyberie prv\u00fdch 50 objedn\u00e1vok zo zoznamu, zoraden\u00fdch pod\u013ea d\u00e1tumu pridania zostupne, in\u00fdmi slovami \u2014 50 najnov\u0161\u00edch objedn\u00e1vok.<\/p>\n<p>V testovacej datab\u00e1ze sa vykon\u00e1va r\u00fdchlo, ale po\u010fme sa pozrie\u0165 na pl\u00e1n vykonania a \u0161tatistiku vstupu a v\u00fdstupu:<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdstup v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom.\" src=\"\/wp-content\/uploads\/2020\/03\/248e4b64593c7000216b46777183d639.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<pre><code class=\"plaintext\">Tabu\u013eka 'SalesOrderHeader'. Po\u010det skenovan\u00ed 1, logick\u00e9 \u010d\u00edtania 698, fyzick\u00e9 \u010d\u00edtania 0, predbe\u017en\u00e9 \u010d\u00edtania 0, logick\u00e9 \u010d\u00edtania LOB 0, fyzick\u00e9 \u010d\u00edtania LOB 0, predbe\u017en\u00e9 \u010d\u00edtania LOB 0.<\/code><\/pre>\n<p>\n<i>Z\u00edska\u0165 \u0161tatistiku vstupu\/v\u00fdstupu pre ka\u017ed\u00fd dotaz je mo\u017en\u00e9 vykonan\u00edm pr\u00edkazu SET STATISTICS IO ON v prostred\u00ed vykon\u00e1vania dotazov.<\/i><\/p>\n<p>Ako je vidie\u0165 z pl\u00e1nu vykonania, najn\u00e1ro\u010dnej\u0161ou oper\u00e1ciou je triedenie v\u0161etk\u00fdch riadkov p\u00f4vodnej tabu\u013eky pod\u013ea d\u00e1tumu pridania. A probl\u00e9m je v tom, \u017ee \u010d\u00edm viac riadkov sa v tabu\u013eke objav\u00ed, t\u00fdm \u0165a\u017e\u0161ie bude triedenie. V praxi by sa tak\u00fdmto situ\u00e1ci\u00e1m malo vyhn\u00fa\u0165, preto prid\u00e1me index na d\u00e1tum pridania a pozrieme sa, \u010di sa zmenila spotreba zdrojov:<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdstup v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom.\" src=\"\/wp-content\/uploads\/2020\/03\/a33e1eadf6f8f8b516b9bb834ad7ad86.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<pre><code class=\"plaintext\">Tabu\u013eka 'SalesOrderHeader'. Po\u010det skenovan\u00ed 1, logick\u00e9 \u010d\u00edtania 165, fyzick\u00e9 \u010d\u00edtania 0, predbe\u017en\u00e9 \u010d\u00edtania 5, logick\u00e9 \u010d\u00edtania LOB 0, fyzick\u00e9 \u010d\u00edtania LOB 0, predbe\u017en\u00e9 \u010d\u00edtania LOB 0.\n<\/code><\/pre>\n<p>\nJe zrejm\u00e9, \u017ee je to ove\u013ea lep\u0161ie. Ale s\u00fa v\u0161etky probl\u00e9my vyrie\u0161en\u00e9? Zmen\u00edme dopyt na vyh\u013ead\u00e1vanie objedn\u00e1vok, kde celkov\u00e1 cena tovaru presahuje 100 dol\u00e1rov:<\/p>\n<pre><code class=\"sql\">SELECT * FROM Sales.SalesOrderHeader\nWHERE SubTotal &gt; 100\nORDER BY OrderDate DESC\nOFFSET 0 ROWS\nFETCH NEXT 50 ROWS ONLY\n<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"V\u00fdstup v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom.\" src=\"\/wp-content\/uploads\/2020\/03\/e057bfc89e11a31c6d2855b93ec3c747.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<pre><code class=\"plaintext\">Tabu\u013eka 'SalesOrderHeader'. Po\u010det skenovan\u00ed 1, logick\u00e9 \u010d\u00edtania 1081, fyzick\u00e9 \u010d\u00edtania 0, \u010d\u00edtania vopred 0, logick\u00e9 \u010d\u00edtania lob 0, fyzick\u00e9 \u010d\u00edtania lob 0, \u010d\u00edtania vopred lob 0.<\/code><\/pre>\n<p>\nM\u00e1me z\u00e1bavn\u00fa situ\u00e1ciu: pl\u00e1n dopytu nie je v\u00fdrazne hor\u0161\u00ed ako predch\u00e1dzaj\u00faci, ale skuto\u010dn\u00fd po\u010det logick\u00fdch \u010d\u00edtan\u00ed je takmer dvakr\u00e1t vy\u0161\u0161\u00ed ako pri \u00faplnom skenovan\u00ed tabu\u013eky. Rie\u0161en\u00edm je vytvori\u0165 z existuj\u00faceho indexu zlo\u017een\u00fd index a prida\u0165 ako druh\u00e9 pole celkov\u00fa cenu tovaru, potom op\u00e4\u0165 z\u00edskame 165 logick\u00fdch \u010d\u00edtan\u00ed:<\/p>\n<pre><code class=\"sql\">CREATE INDEX IX_SalesOrderHeader_OrderDate_SubTotal on Sales.SalesOrderHeader(OrderDate, SubTotal);\n<\/code><\/pre>\n<p>\nT\u00fato s\u00e9riu pr\u00edkladov m\u00f4\u017eeme pokra\u010dova\u0165 dlho, ale dve hlavn\u00e9 my\u0161lienky, ktor\u00e9 tu chcem vyjadri\u0165, s\u00fa:<\/p>\n<ul>\n<li>Pridanie ak\u00e9hoko\u013evek nov\u00e9ho krit\u00e9ria alebo poradia triedenia do dopytu m\u00f4\u017ee v\u00fdrazne ovplyvni\u0165 r\u00fdchlos\u0165 jeho vykonania.<\/li>\n<li>Ale ak potrebujeme z\u00edska\u0165 len \u010das\u0165 \u00fadajov, a nie v\u0161etky v\u00fdsledky, ktor\u00e9 s\u00fa vhodn\u00e9 pre vyh\u013ead\u00e1vacie podmienky, existuje mnoho sp\u00f4sobov, ako optimalizova\u0165 tak\u00fd dopyt.<\/li>\n<\/ul>\n<p>\nTeraz prejdime k druh\u00e9mu dopytu, spomenut\u00e9mu na za\u010diatku \u2013 k tomu, ktor\u00fd po\u010d\u00edta po\u010det z\u00e1znamov, ktor\u00e9 sp\u013a\u0148aj\u00fa vyh\u013ead\u00e1vaciu podmienku. Vezmime ten ist\u00fd pr\u00edklad \u2013 vyh\u013ead\u00e1vanie objedn\u00e1vok, ktor\u00e9 s\u00fa drah\u0161ie ako 100 dol\u00e1rov:<\/p>\n<pre><code class=\"sql\">SELECT COUNT(1) FROM Sales.SalesOrderHeader\nWHERE SubTotal &gt; 100\n<\/code><\/pre>\n<p>\nPri existuj\u00facom zlo\u017eenom indexe, uvedenom vy\u0161\u0161ie, z\u00edskame:<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdstup v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom.\" src=\"\/wp-content\/uploads\/2020\/03\/7beab0c83a50e2d68a83a965df555ec9.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<pre><code class=\"plaintext\">Tabu\u013eka 'SalesOrderHeader'. Po\u010det skenovan\u00ed 1, logick\u00e9 \u010d\u00edtania 698, fyzick\u00e9 \u010d\u00edtania 0, predbe\u017en\u00e9 \u010d\u00edtania 0, logick\u00e9 \u010d\u00edtania LOB 0, fyzick\u00e9 \u010d\u00edtania LOB 0, predbe\u017en\u00e9 \u010d\u00edtania LOB 0.<\/code><\/pre>\n<p>\nNie je prekvapen\u00edm, \u017ee dopyt prech\u00e1dza cel\u00fdm indexom, preto\u017ee pole SubTotal nie je na prvej poz\u00edcii, tak\u017ee dopyt to nem\u00f4\u017ee vyu\u017ei\u0165. Probl\u00e9m sa rie\u0161i pridan\u00edm \u010fal\u0161ieho indexu na pole SubTotal, a na z\u00e1ver to d\u00e1 u\u017e len 48 logick\u00fdch \u010d\u00edtan\u00ed.<\/p>\n<p>M\u00f4\u017eeme uvies\u0165 e\u0161te nieko\u013eko pr\u00edkladov dopytov na po\u010d\u00edtanie, ale podstata zostane rovnak\u00e1: <b>z\u00edskanie d\u00e1vky \u00fadajov a po\u010d\u00edtanie celkov\u00e9ho po\u010dtu \u2013 to s\u00fa dva z\u00e1sadne odli\u0161n\u00e9 dopyty<\/b>, a ka\u017ed\u00fd vy\u017eaduje svoje opatrenia na optimaliz\u00e1ciu. V\u0161eobecne nie je mo\u017en\u00e9 n\u00e1js\u0165 kombin\u00e1ciu indexov, ktor\u00e1 by rovnako dobre fungovala pre oba dopyty.<\/p>\n<p>Jedn\u00fdm z d\u00f4le\u017eit\u00fdch po\u017eiadaviek, ktor\u00e9 je potrebn\u00e9 objasni\u0165 pri v\u00fdvoji tak\u00e9ho vyh\u013ead\u00e1vacieho rie\u0161enia, je, \u010di je pre podnik d\u00f4le\u017eit\u00e9 vidie\u0165 celkov\u00fd po\u010det n\u00e1jden\u00fdch objektov. \u010casto sa uk\u00e1\u017ee, \u017ee nie. A navig\u00e1cia pod\u013ea konkr\u00e9tnych \u010d\u00edsel str\u00e1nok je pod\u013ea m\u0148a rie\u0161en\u00edm s ve\u013emi \u00fazkou oblas\u0165ou aplik\u00e1cie, preto\u017ee v\u00e4\u010d\u0161ina scen\u00e1rov s str\u00e1nkovan\u00edm vyzer\u00e1 ako \u201eprejs\u0165 na \u010fal\u0161iu str\u00e1nku\u201c.<\/p>\n<h2>Mo\u017enos\u0165 str\u00e1nkovania #2<\/h2>\n<p>\nPredpokladajme, \u017ee u\u017e\u00edvate\u013eom nez\u00e1le\u017e\u00ed na vedomosti o celkovom po\u010dte n\u00e1jden\u00fdch objektov. Pok\u00fasme sa zjednodu\u0161i\u0165 vyh\u013ead\u00e1vaciu str\u00e1nku:<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdstup v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom.\" src=\"\/wp-content\/uploads\/2020\/03\/66f5ee6dc1a52f14e55ae31e05c502b2.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nV skuto\u010dnosti sa zmenilo iba to, \u017ee u\u017e nie je mo\u017en\u00e9 prech\u00e1dza\u0165 pod\u013ea konkr\u00e9tnych \u010d\u00edsel str\u00e1nok, a teraz nie je potrebn\u00e9, aby tento tabu\u013eka vedela, ko\u013eko ich celkovo m\u00f4\u017ee by\u0165. Ale vznik\u00e1 ot\u00e1zka \u2014 ako tabu\u013eka zist\u00ed, \u010di existuj\u00fa \u00fadaje pre nasleduj\u00facu str\u00e1nku (aby spr\u00e1vne zobrazila odkaz \u201e\u010eal\u0161ie\u201c)?<\/p>\n<p>Odpove\u010f je ve\u013emi jednoduch\u00e1: m\u00f4\u017eete na\u010d\u00edta\u0165 z datab\u00e1zy o jeden z\u00e1znam viac, ne\u017e je potrebn\u00e9 na zobrazenie, a existencia tohto \u201e\u010fal\u0161ieho\u201c z\u00e1znamu uk\u00e1\u017ee, \u010di je k dispoz\u00edcii \u010fal\u0161ia d\u00e1vka. T\u00fdmto sp\u00f4sobom na z\u00edskanie jednej str\u00e1nky \u00fadajov bude potrebn\u00e9 vykona\u0165 iba jeden dotaz, \u010do v\u00fdrazne zlep\u0161uje v\u00fdkon a u\u013eah\u010duje podporu takejto funk\u010dnosti. Mal som praktick\u00fd pr\u00edpad, ke\u010f vzdanie sa po\u010d\u00edtania celkov\u00e9ho po\u010dtu z\u00e1znamov zr\u00fdchlilo v\u00fdstup v\u00fdsledkov 4-5 kr\u00e1t.<\/p>\n<p>Pre tento pr\u00edstup existuje nieko\u013eko variantov pou\u017e\u00edvate\u013esk\u00e9ho rozhrania: tla\u010didl\u00e1 \u201esp\u00e4\u0165\u201c a \u201edopredu\u201c, ako v uvedenom pr\u00edklade, tla\u010didlo \u201ena\u010d\u00edta\u0165 viac\u201c, ktor\u00e9 jednoducho prid\u00e1va nov\u00fa d\u00e1vku do zobrazen\u00fdch v\u00fdsledkov, \u201enekone\u010dn\u00e9 pos\u00favanie\u201c, ktor\u00e9 funguje na princ\u00edpe \u201ena\u010d\u00edta\u0165 viac\u201c, ale sign\u00e1lom na z\u00edskanie nasleduj\u00facej d\u00e1vky je pos\u00favanie u\u017e\u00edvate\u013eom v\u0161etk\u00fdch vyveden\u00fdch v\u00fdsledkov a\u017e do konca. Nech je u\u017e vizu\u00e1lne rie\u0161enie ak\u00e9ko\u013evek, princ\u00edp v\u00fdberu \u00fadajov zost\u00e1va rovnak\u00fd.<\/p>\n<h2>Nuansy implement\u00e1cie str\u00e1nkovania<\/h2>\n<p>\nVo v\u0161etk\u00fdch pr\u00edkladoch dopytov uveden\u00fdch vy\u0161\u0161ie sa pou\u017e\u00edva pr\u00edstup \u201eposun + po\u010det\u201c, ke\u010f sa v samotnom dopyte uv\u00e1dza, z ktorej poradia riadkov v\u00fdsledku a ak\u00e9 mno\u017estvo riadkov je potrebn\u00e9 vr\u00e1ti\u0165. Najprv sa pozrime, ako najlep\u0161ie organizova\u0165 prenos parametrov v tomto pr\u00edpade. V praxi som sa stretol nieko\u013ek\u00fdmi sp\u00f4sobmi:<\/p>\n<ul>\n<li>\u010c\u00edseln\u00fd index po\u017eadovanej str\u00e1nky (pageIndex), ve\u013ekos\u0165 str\u00e1nky (pageSize).<\/li>\n<li>\u010c\u00edseln\u00fd index prvej polo\u017eky, ktor\u00fa treba vr\u00e1ti\u0165 (startIndex), maxim\u00e1lny po\u010det polo\u017eiek vo v\u00fdsledku (count).<\/li>\n<li>\u010c\u00edseln\u00fd index prvej polo\u017eky, ktor\u00fa treba vr\u00e1ti\u0165 (startIndex), \u010d\u00edseln\u00fd index poslednej polo\u017eky, ktor\u00fa treba vr\u00e1ti\u0165 (endIndex).<\/li>\n<\/ul>\n<p>\nNa prv\u00fd poh\u013ead sa m\u00f4\u017ee zda\u0165, \u017ee je to tak\u00e9 jednoduch\u00e9, \u017ee na tom nez\u00e1le\u017e\u00ed. Ale nie je to tak \u2014 najpohodlnej\u0161ou a najuniverz\u00e1lnej\u0161ou mo\u017enos\u0165ou je druh\u00e1 (startIndex, count). Na to existuje nieko\u013eko d\u00f4vodov:<\/p>\n<ul>\n<li>Pre pr\u00edstup s od\u010d\u00edtan\u00edm +1 polo\u017eky, ktor\u00fd bol uveden\u00fd vy\u0161\u0161ie, je prv\u00e1 mo\u017enos\u0165 s pageIndex a pageSize mimoriadne nepraktick\u00e1. Napr\u00edklad chceme zobrazi\u0165 50 polo\u017eiek na str\u00e1nke. Pod\u013ea uveden\u00e9ho algoritmu je potrebn\u00e9 pre\u010d\u00edta\u0165 o jednu polo\u017eku viac, ne\u017e je potrebn\u00e9. Ak tento \u201e+1\u201c nie je zakomponovan\u00fd na serveri, dostaneme sa k tomu, \u017ee pre prv\u00fa str\u00e1nku mus\u00edme \u017eiada\u0165 polo\u017eky od 1 do 51, pre druh\u00fa \u2014 od 51 do 101 at\u010f. Ak stanov\u00edme ve\u013ekos\u0165 str\u00e1nky na 51 a zvy\u0161ujeme pageIndex, druh\u00e1 str\u00e1nka vr\u00e1ti polo\u017eky od 52 do 102 at\u010f. Preto v prvej mo\u017enosti je jedin\u00fd sp\u00f4sob, ako norm\u00e1lne implementova\u0165 tla\u010didlo pre prechod na \u010fal\u0161iu str\u00e1nku, zakomponova\u0165 na serveri oddelen\u00e9 \u201ezbyto\u010dn\u00fa\u201c polo\u017eku, \u010do bude ve\u013emi nevypovedan\u00fd nuans.<\/li>\n<li>Tretia mo\u017enos\u0165 v\u00f4bec nem\u00e1 zmysel, preto\u017ee pre vykon\u00e1vanie dotazov vo v\u00e4\u010d\u0161ine datab\u00e1z bude aj tak potrebn\u00e9 pren\u00e1\u0161a\u0165 po\u010det, nie index poslednej polo\u017eky. Nech je od\u010d\u00edtanie startIndex z endIndex a jednoduch\u00e1 aritmetick\u00e1 oper\u00e1cia, ale tu je zbyto\u010dn\u00e1.<\/li>\n<\/ul>\n<p>\nTeraz je potrebn\u00e9 op\u00edsa\u0165 nev\u00fdhody implement\u00e1cie str\u00e1nkovania cez \u201eposun + mno\u017estvo\u201c:<\/p>\n<ul>\n<li>Z\u00edskanie ka\u017edej nasleduj\u00facej str\u00e1nky bude n\u00e1kladnej\u0161ie a pomal\u0161ie ne\u017e predch\u00e1dzaj\u00facej, preto\u017ee datab\u00e1ze bude aj tak potrebn\u00e9 prejs\u0165 v\u0161etk\u00fdmi polo\u017ekami \u201eod za\u010diatku\u201c pod\u013ea krit\u00e9ri\u00ed vyh\u013ead\u00e1vania a triedenia, a potom sa zastavi\u0165 na potrebnom \u00faseku.<\/li>\n<li>Nie v\u0161etky SGBD m\u00f4\u017eu podporova\u0165 tento pr\u00edstup.<\/li>\n<\/ul>\n<p>\nAlternat\u00edvy existuj\u00fa, ale ani tie nie s\u00fa dokonal\u00e9. Prv\u00fd z t\u00fdchto pr\u00edstupov sa naz\u00fdva \u201ekeyset paging\u201c alebo \u201eseek method\u201c a spo\u010d\u00edva v nasleduj\u00facom: po z\u00edskan\u00ed d\u00e1vky si m\u00f4\u017eete zapam\u00e4ta\u0165 hodnoty pol\u00ed v poslednej polo\u017eke na str\u00e1nke, a potom ich pou\u017ei\u0165 na z\u00edskanie nasleduj\u00facej d\u00e1vky. Napr\u00edklad, vykonali sme tak\u00fdto dotaz:<\/p>\n<pre><code class=\"sql\">SELECT * FROM Sales.SalesOrderHeader\nORDER BY OrderDate DESC\nOFFSET 0 ROWS\nFETCH NEXT 50 ROWS ONLY\n<\/code><\/pre>\n<p>\nA v poslednom z\u00e1pise sme dostali hodnotu d\u00e1tumu objedn\u00e1vky '2014-06-29'. Potom pre z\u00edskanie nasleduj\u00facej str\u00e1nky mo\u017eno vysk\u00fa\u0161a\u0165 vykona\u0165 tak\u00e9to:<\/p>\n<pre><code class=\"sql\">SELECT * FROM Sales.SalesOrderHeader\nWHERE OrderDate &lt; &#039;2014-06-29&#039;\nORDER BY OrderDate DESC\nOFFSET 0 ROWS\nFETCH NEXT 50 ROWS ONLY\n<\/code><\/pre>\n<p>\nProbl\u00e9m je v tom, \u017ee OrderDate nie je unik\u00e1tne pole a podmienka uveden\u00e1 vy\u0161\u0161ie s ve\u013ekou pravdepodobnos\u0165ou presko\u010d\u00ed ve\u013ea potrebn\u00fdch riadkov. Aby sme spravili tento dotaz jednozna\u010dn\u00fdm, mus\u00edme k podmienke prida\u0165 unik\u00e1tne pole (predpokladajme, \u017ee 75074 je posledn\u00e1 hodnota prim\u00e1rneho k\u013e\u00fa\u010da z prvej d\u00e1vky):<\/p>\n<pre><code class=\"sql\">SELECT * FROM Sales.SalesOrderHeader\nWHERE (OrderDate = '2014-06-29' AND SalesOrderID &lt; 75074)\n   OR (OrderDate &lt; &#039;2014-06-29&#039;)\nORDER BY OrderDate DESC, SalesOrderID DESC\nOFFSET 0 ROWS\nFETCH NEXT 50 ROWS ONLY\n<\/code><\/pre>\n<p>\nT\u00e1to mo\u017enos\u0165 bude fungova\u0165 spr\u00e1vne, ale vo v\u0161eobecnosti bude \u0165a\u017ek\u00e9 ju optimalizova\u0165, preto\u017ee podmienka obsahuje oper\u00e1tor OR. Ak s rastom OrderDate rastie hodnota prim\u00e1rneho k\u013e\u00fa\u010da, potom sa podmienka m\u00f4\u017ee zjednodu\u0161i\u0165 a necha\u0165 iba filter pod\u013ea SalesOrderID. Ak v\u0161ak medzi hodnotami prim\u00e1rneho k\u013e\u00fa\u010da a po\u013eom, pod\u013ea ktor\u00e9ho je v\u00fdsledok zoraden\u00fd, nie je pr\u00edsna korel\u00e1cia \u2014 vo v\u00e4\u010d\u0161ine DBMS sa tomuto OR nebude da\u0165 vyhn\u00fa\u0165. Mne zn\u00e1ma v\u00fdnimka je PostgreSQL, kde sa plne podporuje porovn\u00e1vanie k-t\u00edc, a vy\u0161\u0161ie uveden\u00fa podmienku mo\u017eno zap\u00edsa\u0165 ako \u201eWHERE (OrderDate, SalesOrderID) &lt; (&#039;2014-06-29&#039;, 75074)\u201c. Pri existencii zlo\u017een\u00e9ho k\u013e\u00fa\u010da s t\u00fdmito dvoma po\u013eami by mal by\u0165 tak\u00fdto dotaz dos\u0165 jednoduch\u00fd.<\/p>\n<p>Druh\u00fd alternat\u00edvny pr\u00edstup m\u00f4\u017eeme vidie\u0165 napr\u00edklad v <noindex><a rel=\"nofollow\" href=\"https:\/\/www.elastic.co\/guide\/en\/elasticsearch\/reference\/6.8\/search-request-scroll.html\">ElasticSearch scroll API<\/a><\/noindex> alebo <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/@gary.strange\/understanding-cosmosdb-continuation-tokens-hasmoreresults-and-connectionpolicy-requesttimeouts-3ed1fadfa81d\">Cosmos DB<\/a><\/noindex> \u2014 kde dopyt okrem \u00fadajov vracia \u0161peci\u00e1lny identifik\u00e1tor, pomocou ktor\u00e9ho m\u00f4\u017eeme z\u00edska\u0165 \u010fal\u0161iu v\u00e1rku \u00fadajov. Ak m\u00e1 tento identifik\u00e1tor neobmedzen\u00fa \u017eivotnos\u0165 (ako v Comsos DB), je to vynikaj\u00faci sp\u00f4sob implement\u00e1cie str\u00e1nkovania s postupn\u00fdm prechodom medzi str\u00e1nkami (mo\u017enos\u0165 #2 uveden\u00e1 vy\u0161\u0161ie). Jeho mo\u017en\u00e9 nev\u00fdhody: nie je podporovan\u00fd vo v\u0161etk\u00fdch DBMS; z\u00edskan\u00fd identifik\u00e1tor \u010fal\u0161ej d\u00e1vky m\u00f4\u017ee ma\u0165 obmedzen\u00fa \u017eivotnos\u0165, \u010do vo v\u0161eobecnosti nie je vhodn\u00e9 na realiz\u00e1ciu interakcie s pou\u017e\u00edvate\u013eom (ako napr\u00edklad ElasticSearch scroll API).<\/p>\n<h2>Zlo\u017eit\u00e1 filtr\u00e1cia<\/h2>\n<p>\nS\u00fa\u0165a\u017e zlo\u017e\u00edme \u010falej. Predpokladajme, \u017ee sa objavil po\u017eiadavok implementova\u0165 tzv. faceted search, v\u0161etk\u00fdm zn\u00e1me z internetov\u00fdch obchodov. Predch\u00e1dzaj\u00face pr\u00edklady zalo\u017een\u00e9 na tabu\u013eke objedn\u00e1vok nie s\u00fa v tomto pr\u00edpade ve\u013emi p\u00fatav\u00e9, preto prejdeme na tabu\u013eku Produkt z datab\u00e1zy AdventureWorks:<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdstup v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom.\" src=\"\/wp-content\/uploads\/2020\/03\/070890a3cb79de3edc69b60b5300efe7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nO \u010do ide vo faceted search? O to, \u017ee pre ka\u017ed\u00fd prvok filtra sa zobrazuje po\u010det zaznamenan\u00ed, ktor\u00e9 zodpovedaj\u00fa tomuto krit\u00e9riu. <i>s oh\u013eadom na filtre zvolen\u00fdch vo v\u0161etk\u00fdch ostatn\u00fdch kateg\u00f3ri\u00e1ch.<\/i>.<\/p>\n<p>Napr\u00edklad, ak vyberieme v tomto pr\u00edklade kateg\u00f3riu Bicykle a farbu \u010cierna, tabu\u013eka zobraz\u00ed len bicykle \u010diernej farby, ale z\u00e1rove\u0148:<\/p>\n<ul>\n<li>Pre ka\u017ed\u00fd krit\u00e9rium skupiny \u00abKateg\u00f3rie\u00bb sa zobraz\u00ed po\u010det produktov z tejto kateg\u00f3rie \u010diernej farby.<\/li>\n<li>Pre ka\u017ed\u00fd krit\u00e9rium skupiny \u00abFarby\u00bb sa zobraz\u00ed po\u010det bicyklov tejto farby.<\/li>\n<\/ul>\n<p>\nTu je pr\u00edklad v\u00fdstupu v\u00fdsledkov pre tak\u00e9to podmienky:<\/p>\n<p><img decoding=\"async\" alt=\"V\u00fdstup v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom.\" src=\"\/wp-content\/uploads\/2020\/03\/7c8ec4d8b427f1f59f0129afebe74b08.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAk navy\u0161e za\u0161krtneme kateg\u00f3riu \u00abOdevy\u00bb, tabu\u013eka zobraz\u00ed aj oble\u010denie \u010diernej farby, ktor\u00e9 je k dispoz\u00edcii. Po\u010det produktov \u010diernej farby v sekcii \u00abFarba\u00bb sa tie\u017e prepo\u010d\u00edta pod\u013ea nov\u00fdch podmienok, len v sekcii \u00abKateg\u00f3rie\u00bb sa ni\u010d nezmen\u00ed\u2026 D\u00fafam, \u017ee t\u00fdchto pr\u00edkladov je dos\u0165 na pochopenie be\u017en\u00e9ho algoritmu fungovania faceted search.<\/p>\n<p>Teraz si predstavme, ako to m\u00f4\u017eeme implementova\u0165 v rela\u010dnej datab\u00e1ze. Ka\u017ed\u00e1 skupina krit\u00e9ri\u00ed, ako je Kateg\u00f3ria a Farba, si vy\u017eaduje samostatn\u00fd dopyt:<\/p>\n<pre><code class=\"sql\">SELECT pc.ProductCategoryID, pc.Name, COUNT(1) FROM Production.Product p\n  INNER JOIN Production.ProductSubcategory ps ON p.ProductSubcategoryID = ps.ProductSubcategoryID\n  INNER JOIN Production.ProductCategory pc ON ps.ProductCategoryID = pc.ProductCategoryID\nWHERE p.Color = 'Black'\nGROUP BY pc.ProductCategoryID, pc.Name\nORDER BY COUNT(1) DESC\n<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"V\u00fdstup v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom.\" src=\"\/wp-content\/uploads\/2020\/03\/3b59b68ce934c4ec1630ec649e68ccdb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<pre><code class=\"sql\">SELECT Color, COUNT(1) FROM Production.Product p\n  INNER JOIN Production.ProductSubcategory ps ON p.ProductSubcategoryID = ps.ProductSubcategoryID\nWHERE ps.ProductCategoryID = 1 --Bicykle\nGROUP BY Color\nORDER BY COUNT(1) DESC\n<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"V\u00fdstup v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom.\" src=\"\/wp-content\/uploads\/2020\/03\/82e1e6ab0fae683d383e3fecf4e3a15a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n\u010co je na tomto rie\u0161en\u00ed zl\u00e9? Ve\u013emi jednoducho \u2014 je n\u00edm zle \u0161k\u00e1lovate\u013en\u00e9. Ka\u017ed\u00e1 sekcia filtra vy\u017eaduje samostatn\u00fd dopyt na po\u010d\u00edtanie mno\u017estiev a tieto dopyty nie s\u00fa pr\u00e1ve naj\u013eah\u0161ie. V internetov\u00fdch obchodoch m\u00f4\u017eu by\u0165 v niektor\u00fdch rubrik\u00e1ch aj nieko\u013eko desiatok sekci\u00ed filtra, \u010do m\u00f4\u017ee predstavova\u0165 v\u00e1\u017eny probl\u00e9m pre v\u00fdkonnos\u0165.<\/p>\n<p>Obvykle po t\u00fdchto tvrdeniach mi pon\u00fakaj\u00fa niektor\u00e9 rie\u0161enia, a to:<\/p>\n<ul>\n<li>Spoji\u0165 v\u0161etky po\u010dty do jedn\u00e9ho dotazu. Z technick\u00e9ho h\u013eadiska je to mo\u017en\u00e9 pomocou k\u013e\u00fa\u010dov\u00e9ho slova UNION, ale v\u00fdkonu to ve\u013emi nepom\u00f4\u017ee \u2014 datab\u00e1za bude musie\u0165 ka\u017ed\u00fd z fragmentov vykona\u0165 \"od nuly\".<\/li>\n<li>Ke\u0161ova\u0165 po\u010dty. Toto mi navrhuj\u00fa prakticky zaka\u017ed\u00fdm, ke\u010f popisujem probl\u00e9m. Nuansa je v tom, \u017ee to je vo v\u0161eobecnosti nemo\u017en\u00e9. Predpokladajme, \u017ee m\u00e1me 10 \u201ef\u00e1s\u201d s 5 hodnotami v ka\u017edej. To je ve\u013emi \u201eskromn\u00e1\u201c situ\u00e1cia v porovnan\u00ed s t\u00fdm, \u010do je mo\u017en\u00e9 vidie\u0165 v rovnak\u00fdch internetov\u00fdch obchodoch. V\u00fdber jedn\u00e9ho prvku f\u00e1zy ovplyv\u0148uje po\u010dty v 9 in\u00fdch, in\u00fdmi slovami, pre ka\u017ed\u00fa kombin\u00e1ciu krit\u00e9ri\u00ed m\u00f4\u017eu by\u0165 po\u010dty r\u00f4zne. Celkovo v na\u0161om pr\u00edklade existuje 50 krit\u00e9ri\u00ed, ktor\u00e9 si m\u00f4\u017ee pou\u017e\u00edvate\u013e vybra\u0165, a teda existuje 250 mo\u017en\u00fdch kombin\u00e1ci\u00ed. Na naplnenie takejto d\u00e1tovej \u0161trukt\u00fary nebude dostatok pam\u00e4te ani \u010dasu. Tu sa d\u00e1 namieta\u0165 a poveda\u0165, \u017ee nie v\u0161etky kombin\u00e1cie s\u00fa re\u00e1lne a pou\u017e\u00edvate\u013e zriedka vyberie viac ako 5-10 krit\u00e9ri\u00ed. \u00c1no, je mo\u017en\u00e9 urobi\u0165 leniv\u00fa na\u010d\u00edtanie a ke\u0161ova\u0165 po\u010dty len pre to, \u010do bolo kedy vybran\u00e9, ale \u010d\u00edm viac bude mo\u017enost\u00ed v\u00fdberu, t\u00fdm menej efekt\u00edvny bude tak\u00fd ke\u0161 a t\u00fdm vidite\u013enej\u0161ie bud\u00fa probl\u00e9my s \u010dasom odozvy (najm\u00e4 ak sa s\u00fabor \u00fadajov pravidelne men\u00ed).<\/li>\n<\/ul>\n<p>\nNa\u0161\u0165astie, podobn\u00e1 \u00faloha u\u017e d\u00e1vno m\u00e1 dostato\u010dne efekt\u00edvne rie\u0161enia, ktor\u00e9 predv\u00eddate\u013ene funguj\u00fa na ve\u013ek\u00fdch objemoch \u00fadajov. Pre ktor\u00fako\u013evek z t\u00fdchto mo\u017enost\u00ed m\u00e1 zmysel rozdeli\u0165 prepo\u010det f\u00e1s a z\u00edskanie str\u00e1nky v\u00fdsledkov na dva paraleln\u00e9 po\u017eiadavky na server a usporiada\u0165 pou\u017e\u00edvate\u013esk\u00e9 rozhranie tak, aby na\u010d\u00edtanie \u00fadajov o f\u00e1zach \u201eneprek\u00e1\u017ealo\u201c zobrazovaniu v\u00fdsledkov vyh\u013ead\u00e1vania.<\/p>\n<ul>\n<li>Vy\u017eaduje sa, aby bol cel\u00fd prepo\u010det \u201ef\u00e1siek\u201c vykon\u00e1van\u00fd \u010do najr menos. Napr\u00edklad, netreba znova prepo\u010d\u00edtava\u0165 v\u0161etko pri ka\u017edej zmene vyh\u013ead\u00e1vac\u00edch krit\u00e9ri\u00ed, namiesto toho n\u00e1jdite celkov\u00fd po\u010det v\u00fdsledkov, ktor\u00e9 zodpovedaj\u00fa aktu\u00e1lnym podmienkam, a navrhnite pou\u017e\u00edvate\u013eovi ich zobrazi\u0165 \u2014 \u201eBolo n\u00e1jden\u00fdch 1425 z\u00e1znamov, zobrazi\u0165?\u201c Pou\u017e\u00edvate\u013e m\u00f4\u017ee bu\u010f pokra\u010dova\u0165 v zmene podmienok vyh\u013ead\u00e1vania, alebo stla\u010di\u0165 tla\u010didlo \u201ezobrazi\u0165\u201c. Iba v druhom pr\u00edpade bud\u00fa splnen\u00e9 v\u0161etky po\u017eiadavky na z\u00edskanie v\u00fdsledkov a prepo\u010det po\u010dtov na v\u0161etk\u00fdch \u201ef\u00e1skach\u201c. Pri tom, ako nie je \u0165a\u017ek\u00e9 si v\u0161imn\u00fa\u0165, budeme musie\u0165 zvl\u00e1dnu\u0165 po\u017eiadavku na z\u00edskanie celkov\u00e9ho po\u010dtu v\u00fdsledkov a jeho optimaliz\u00e1ciu. Tento pr\u00edstup mo\u017eno vidie\u0165 v mnoh\u00fdch mal\u00fdch internetov\u00fdch obchodoch. Je zrejm\u00e9, \u017ee to nie je v\u0161eliek na tento probl\u00e9m, ale v jednoduch\u00fdch pr\u00edpadoch m\u00f4\u017ee by\u0165 celkom dobr\u00fdm kompromisom.<\/li>\n<li>Pou\u017eite vyh\u013ead\u00e1vac\u00ed engin na vyh\u013ead\u00e1vanie v\u00fdsledkov a po\u010d\u00edtanie f\u00e1siek, ako s\u00fa Solr, ElasticSearch, Sphinx a \u010fal\u0161ie. V\u0161etky s\u00fa navrhnut\u00e9 na kon\u0161trukciu \u201ef\u00e1siek\u201c a robia to dostato\u010dne efekt\u00edvne v\u010faka inverzn\u00e9mu indexu. Ako s\u00fa usporiadan\u00e9 vyh\u013ead\u00e1vacie syst\u00e9my, pre\u010do s\u00fa v t\u00fdchto pr\u00edpadoch \u00fa\u010dinnej\u0161ie ne\u017e datab\u00e1zy v\u0161eobecn\u00e9ho ur\u010denia, ak\u00e9 s\u00fa tu praktiky a \u00faskalia \u2014 to je t\u00e9ma na samostatn\u00fd \u010dl\u00e1nok. Chcem v\u0161ak pouk\u00e1za\u0165 na to, \u017ee vyh\u013ead\u00e1vac\u00ed engin nem\u00f4\u017ee nahradi\u0165 hlavn\u00e9 \u00falo\u017eisko d\u00e1t, pou\u017e\u00edva sa ako doplnok: ak\u00e9ko\u013evek zmeny v hlavnej datab\u00e1ze, ktor\u00e9 s\u00fa d\u00f4le\u017eit\u00e9 pre vyh\u013ead\u00e1vanie, sa synchronizuj\u00fa do vyh\u013ead\u00e1vacieho indexu; mechanizmus vyh\u013ead\u00e1vania be\u017ene interaguje iba s vyh\u013ead\u00e1vac\u00edm enginom a neobr\u00e1ti sa na hlavn\u00fa datab\u00e1zu. Jeden z najd\u00f4le\u017eitej\u0161\u00edch aspektov tu \u2014 ako organizova\u0165 t\u00fato synchroniz\u00e1ciu spo\u013eahlivo. V\u0161etko z\u00e1vis\u00ed od po\u017eiadaviek na \u201e\u010das reakcie\u201c. Ak \u010das medzi zmenou v hlavnej datab\u00e1ze a jej \u201eprejaven\u00edm\u201c vo vyh\u013ead\u00e1van\u00ed nie je kritick\u00fd, je mo\u017en\u00e9 vytvori\u0165 slu\u017ebu, ktor\u00e1 ka\u017ed\u00fdch p\u00e1r min\u00fat h\u013ead\u00e1 ned\u00e1vno zmenen\u00e9 z\u00e1znamy a ich indexuje. Ak je potrebn\u00fd minim\u00e1lne mo\u017en\u00fd \u010das reakcie, m\u00f4\u017eete implementova\u0165 nie\u010do ako <noindex><a rel=\"nofollow\" href=\"https:\/\/microservices.io\/patterns\/data\/transactional-outbox.html\">transactional outbox<\/a><\/noindex> na odosielanie aktualiz\u00e1ci\u00ed do vyh\u013ead\u00e1vacieho servisu.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Zhrnutie<\/h2>\n<p><\/p>\n<ol>\n<li>Implement\u00e1cia str\u00e1nkovania na strane servera je v\u00e1\u017enym zlo\u017eit\u00fdm procesom a m\u00e1 zmysel ju aplikova\u0165 iba pre r\u00fdchlo rast\u00face alebo jednoducho ve\u013ek\u00e9 d\u00e1ta. Neexistuje presn\u00fd recept, ako pos\u00fadi\u0165, \u010do je 've\u013ek\u00e9' alebo 'r\u00fdchlo rast\u00face', ale ja by som sa dr\u017eal tohto pr\u00edstupu:\n<ul>\n<li>Ak z\u00edskanie celej kolekcie \u00fadajov s oh\u013eadom na \u010das servera a prenos po sieti norm\u00e1lne spad\u00e1 do po\u017eiadaviek na v\u00fdkon, nem\u00e1 zmysel realizova\u0165 str\u00e1nkovanie na strane servera.<\/li>\n<li>M\u00f4\u017ee nasta\u0165 situ\u00e1cia, \u017ee v bl\u00edzkej dobe sa nepredpokladaj\u00fa probl\u00e9my s v\u00fdkonom, preto\u017ee d\u00e1ta s\u00fa m\u00e1lo, ale kolekcia \u00fadajov neust\u00e1le rastie. Ak nejak\u00fd s\u00fabor \u00fadajov bude v bud\u00facnosti pravdepodobne prest\u00e1va\u0165 vyhovova\u0165 predch\u00e1dzaj\u00facemu bodu, je lep\u0161ie zahrn\u00fa\u0165 str\u00e1nkovanie hne\u010f.<\/li>\n<\/ul>\n<\/li>\n<li>Ak z poh\u013eadu podnikania neexistuje pr\u00edsne po\u017eiadavky na zobrazenie celkov\u00e9ho mno\u017estva v\u00fdsledkov alebo na zobrazenie \u010d\u00edsel str\u00e1nok a vo va\u0161om syst\u00e9me nie je vyh\u013ead\u00e1vac\u00ed engine, je lep\u0161ie tieto aspekty nerealizova\u0165 a zv\u00e1\u017ei\u0165 mo\u017enos\u0165 \u010d. 2.<\/li>\n<li>Ak existuje jasn\u00e9 po\u017eiadavka na faceted search, m\u00e1te dve mo\u017enosti, ako nestrati\u0165 v\u00fdkon:\n<ul>\n<li>Nemus\u00edte prepo\u010d\u00edtava\u0165 v\u0161etky mno\u017estv\u00e1 pri ka\u017edej zmene krit\u00e9ri\u00ed vyh\u013ead\u00e1vania.<\/li>\n<li>Pou\u017ei\u0165 vyh\u013ead\u00e1vac\u00ed engine ako Solr, ElasticSearch, Sphinx a in\u00e9. Ale treba si uvedomi\u0165, \u017ee nem\u00f4\u017ee by\u0165 n\u00e1hradou za hlavn\u00fa datab\u00e1zu a mal by by\u0165 pou\u017eit\u00fd ako doplnok k hlavn\u00e9mu \u00falo\u017eisku na rie\u0161enie vyh\u013ead\u00e1vac\u00edch \u00faloh. <\/li>\n<\/ul>\n<\/li>\n<li>Rovnako pri faceted search m\u00e1 zmysel rozdeli\u0165 z\u00edskanie str\u00e1nok v\u00fdsledkov vyh\u013ead\u00e1vania a prepo\u010d\u00edtanie mno\u017estva na dva paraleln\u00e9 dotazy. Prepo\u010d\u00edtanie mno\u017estva m\u00f4\u017ee trva\u0165 dlh\u0161ie ako z\u00edskanie v\u00fdsledkov, pri\u010dom v\u00fdsledky s\u00fa pre pou\u017e\u00edvate\u013ea d\u00f4le\u017eitej\u0161ie.<\/li>\n<li>Ak pou\u017e\u00edvate SQL datab\u00e1zu na vyh\u013ead\u00e1vanie, ak\u00e1ko\u013evek zmena k\u00f3du t\u00fdkaj\u00faca sa tejto \u010dasti by mala by\u0165 d\u00f4kladne testovan\u00e1 z h\u013eadiska v\u00fdkonu na pr\u00edslu\u0161nom objeme \u00fadajov (prevy\u0161uj\u00facom objem v '\u017eiv\u00e9' datab\u00e1ze). Odpor\u00fa\u010da sa tie\u017e pou\u017e\u00edva\u0165 monitorovanie \u010dasov vykon\u00e1vania dotazov na v\u0161etk\u00fdch in\u0161tanci\u00e1ch datab\u00e1zy, a najm\u00e4 \u2014 na '\u017eivom'. Aj ke\u010f v \u0161t\u00e1diu v\u00fdvoja pl\u00e1ny dotazov vych\u00e1dzali dobre, s rastom objemu d\u00e1t sa situ\u00e1cia m\u00f4\u017ee v\u00fdrazne zmeni\u0165.<\/li>\n<\/ol>\n<p>Zdroj: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/epam_systems\/blog\/493438\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041e\u0434\u0438\u043d \u0438\u0437 \u0442\u0438\u043f\u043e\u0432\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0432\u043e \u0432\u0441\u0435\u0445 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u0445 \u043d\u0430\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u2014 \u043f\u043e\u0438\u0441\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c \u0438 \u0432\u044b\u0432\u043e\u0434 \u0438\u0445 \u0432 \u0443\u0434\u043e\u0431\u043d\u043e\u043c \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0432\u0438\u0434\u0435. \u0422\u0443\u0442 \u0436\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0435, \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0435, \u043f\u043e\u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043d\u043e\u043c\u0443 \u0432\u044b\u0432\u043e\u0434\u0443. \u0417\u0430\u0434\u0430\u0447\u0430, \u043f\u043e \u0438\u0434\u0435\u0435, \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u0430\u044f, \u043d\u043e \u043f\u0440\u0438 \u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0434\u0435\u043b\u0430\u044e\u0442 \u0440\u044f\u0434 \u043e\u0448\u0438\u0431\u043e\u043a, \u0438\u0437-\u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0442\u043e\u043c \u0441\u0442\u0440\u0430\u0434\u0430\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":75531,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-75530","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.4 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041e\u0434\u0438\u043d \u0438\u0437 \u0442\u0438\u043f\u043e\u0432\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0432\u043e \u0432\u0441\u0435\u0445 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u0445 \u043d\u0430\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u2014 \u043f\u043e\u0438\u0441\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c \u0438 \u0432\u044b\u0432\u043e\u0434 \u0438\u0445 \u0432 \u0443\u0434\u043e\u0431\u043d\u043e\u043c \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0432\u0438\u0434\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/vyvod-rezultatov-poiska-i-problemy-s-proizvoditelnostyu\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sk_SK\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0412\u044b\u0432\u043e\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041e\u0434\u0438\u043d \u0438\u0437 \u0442\u0438\u043f\u043e\u0432\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0432\u043e \u0432\u0441\u0435\u0445 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u0445 \u043d\u0430\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u2014 \u043f\u043e\u0438\u0441\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c \u0438 \u0432\u044b\u0432\u043e\u0434 \u0438\u0445 \u0432 \u0443\u0434\u043e\u0431\u043d\u043e\u043c \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0432\u0438\u0434\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/vyvod-rezultatov-poiska-i-problemy-s-proizvoditelnostyu\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-03-26T17:42:23+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-03-26T17:42:23+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Zobrazenie v\u00fdsledkov vyh\u013ead\u00e1vania a probl\u00e9my s v\u00fdkonom | ProHoster","description":"Jedn\u00fdm z be\u017en\u00fdch scen\u00e1rov vo v\u0161etk\u00fdch zn\u00e1mich aplik\u00e1ci\u00e1ch je vyh\u013ead\u00e1vanie d\u00e1t pod\u013ea ur\u010dit\u00fdch krit\u00e9ri\u00ed a ich zobrazenie v preh\u013eadnej forme.","canonical_url":"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/vyvod-rezultatov-poiska-i-problemy-s-proizvoditelnostyu","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sk_SK","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0412\u044b\u0432\u043e\u0434 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e | ProHoster","og:description":"\u041e\u0434\u0438\u043d \u0438\u0437 \u0442\u0438\u043f\u043e\u0432\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0432\u043e \u0432\u0441\u0435\u0445 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u0445 \u043d\u0430\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u2014 \u043f\u043e\u0438\u0441\u043a \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u043a\u0440\u0438\u0442\u0435\u0440\u0438\u044f\u043c \u0438 \u0432\u044b\u0432\u043e\u0434 \u0438\u0445 \u0432 \u0443\u0434\u043e\u0431\u043d\u043e\u043c \u0434\u043b\u044f \u0447\u0442\u0435\u043d\u0438\u044f \u0432\u0438\u0434\u0435.","og:url":"https:\/\/prohoster.info\/sk\/blog\/administrirovanie\/vyvod-rezultatov-poiska-i-problemy-s-proizvoditelnostyu","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-03-26T17:42:23+00:00","article:modified_time":"2020-03-26T17:42:23+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"75530","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 17:55:26","updated":"2022-10-02 02:12:16","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/posts\/75530","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/comments?post=75530"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/posts\/75530\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/media\/75531"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/media?parent=75530"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/categories?post=75530"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sk\/wp-json\/wp\/v2\/tags?post=75530"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}