MeklÄ“Å”anas rezultātu izvades un veiktspējas problēmas

Viens no tipiskiem scenārijiem visās mums pazÄ«stamajās lietojumprogrammās ir datu meklÄ“Å”ana pēc noteiktiem kritērijiem un to attēloÅ”ana viegli lasāmā formā. Var bÅ«t arÄ« papildu kārtoÅ”anas, grupÄ“Å”anas un lapoÅ”anas opcijas. Uzdevums teorētiski ir triviāls, taču, to risinot, daudzi izstrādātāji pieļauj vairākas kļūdas, kas vēlāk liek ciest produktivitātei. Mēģināsim apsvērt dažādas iespējas Ŕīs problēmas risināŔanai un formulēsim ieteikumus efektÄ«vākās ievieÅ”anas izvēlei.

MeklÄ“Å”anas rezultātu izvades un veiktspējas problēmas

Peidžeru opcija Nr. 1

VienkārŔākā iespēja, kas nāk prātā, ir meklÄ“Å”anas rezultātu rādÄ«Å”ana pa lappusēm klasiskākajā formā.

MeklÄ“Å”anas rezultātu izvades un veiktspējas problēmas
Pieņemsim, ka jÅ«su lietojumprogramma izmanto relāciju datu bāzi. Å ajā gadÄ«jumā, lai parādÄ«tu informāciju Å”ajā veidlapā, jums bÅ«s jāpalaiž divi SQL vaicājumi:

  • IegÅ«t rindas paÅ”reizējai lapai.
  • Aprēķiniet kopējo rindu skaitu, kas atbilst meklÄ“Å”anas kritērijiem - tas ir nepiecieÅ”ams, lai parādÄ«tu lapas.

Apskatīsim pirmo vaicājumu, kā piemēru izmantojot testa MS SQL datu bāzi AdventureWorks 2016. gada serverim. Šim nolūkam izmantosim tabulu Sales.SalesOrderHeader:

SELECT * FROM Sales.SalesOrderHeader
ORDER BY OrderDate DESC
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY

IepriekÅ” minētais vaicājums atgriezÄ«s pirmos 50 pasÅ«tÄ«jumus no saraksta, kas sakārtoti pēc pievienoÅ”anas datuma dilstoŔā secÄ«bā, citiem vārdiem sakot, 50 jaunākie pasÅ«tÄ«jumi.

TestÄ“Å”anas bāzē tas darbojas ātri, taču apskatÄ«sim izpildes plānu un I/O statistiku:

MeklÄ“Å”anas rezultātu izvades un veiktspējas problēmas

Table 'SalesOrderHeader'. Scan count 1, logical reads 698, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Katra vaicājuma I/O statistiku var iegūt, vaicājuma izpildlaikā palaižot komandu SET STATISTICS IO ON.

Kā redzams izpildes plānā, resursietilpÄ«gākā iespēja ir kārtot visas avota tabulas rindas pēc pievienoÅ”anas datuma. Un problēma ir tā, ka, jo vairāk rindu parādÄ«sies tabulā, jo ā€œgrÅ«tākaā€ bÅ«s ŔķiroÅ”ana. Praksē no Ŕādām situācijām vajadzētu izvairÄ«ties, tāpēc pievienosim indeksu pievienoÅ”anas datumam un paskatÄ«simies, vai resursu patēriņŔ ir mainÄ«jies:

MeklÄ“Å”anas rezultātu izvades un veiktspējas problēmas

Table 'SalesOrderHeader'. Scan count 1, logical reads 165, physical reads 0, read-ahead reads 5, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

AcÄ«mredzot tas ir kļuvis daudz labāks. Bet vai visas problēmas ir atrisinātas? MainÄ«sim vaicājumu, lai meklētu pasÅ«tÄ«jumus, kuru kopējās preču izmaksas pārsniedz 100 ASV dolārus:

SELECT * FROM Sales.SalesOrderHeader
WHERE SubTotal > 100
ORDER BY OrderDate DESC
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY

MeklÄ“Å”anas rezultātu izvades un veiktspējas problēmas

Table 'SalesOrderHeader'. Scan count 1, logical reads 1081, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Mums ir smieklÄ«ga situācija: vaicājumu plāns nav daudz sliktāks par iepriekŔējo, bet faktiskais loÄ£isko nolasÄ«jumu skaits ir gandrÄ«z divreiz lielāks nekā ar pilnu tabulu skenÄ“Å”anu. Ir izeja - ja izveidosim saliktu indeksu no jau esoÅ”a indeksa un kā otro lauku pievienosim kopējo preču cenu, atkal iegÅ«sim 165 loÄ£iskus nolasÄ«jumus:

CREATE INDEX IX_SalesOrderHeader_OrderDate_SubTotal on Sales.SalesOrderHeader(OrderDate, SubTotal);

Å o piemēru sēriju var turpināt vēl ilgi, bet divas galvenās domas, kuras es vēlos izteikt Å”eit, ir:

  • Jebkura jauna kritērija vai kārtoÅ”anas secÄ«bas pievienoÅ”ana meklÄ“Å”anas vaicājumam var bÅ«tiski ietekmēt meklÄ“Å”anas vaicājuma ātrumu.
  • Bet, ja mums ir jāatņem tikai daļa datu, nevis visi rezultāti, kas atbilst meklÄ“Å”anas vienumiem, ir daudz veidu, kā optimizēt Ŕādu vaicājumu.

Tagad pāriesim pie otrā vaicājuma, kas minēts paŔā sākumā ā€“ tā, kas uzskaita meklÄ“Å”anas kritērijam atbilstoÅ”o ierakstu skaitu. Ņemsim to paÅ”u piemēru ā€” meklējot pasÅ«tÄ«jumus, kuru vērtÄ«ba pārsniedz 100 ASV dolārus:

SELECT COUNT(1) FROM Sales.SalesOrderHeader
WHERE SubTotal > 100

Ņemot vērā iepriekÅ” norādÄ«to salikto indeksu, mēs iegÅ«stam:

MeklÄ“Å”anas rezultātu izvades un veiktspējas problēmas

Table 'SalesOrderHeader'. Scan count 1, logical reads 698, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Tas, ka vaicājums iet cauri visam indeksam, nav pārsteidzoÅ”s, jo lauks SubTotal nav pirmajā pozÄ«cijā, tāpēc vaicājums to nevar izmantot. Problēma tiek atrisināta, pievienojot vēl vienu indeksu laukā SubTotal, un rezultātā tas dod tikai 48 loÄ£iskus nolasÄ«jumus.

Varat sniegt vēl dažus daudzumu skaitÄ«Å”anas pieprasÄ«jumu piemērus, taču bÅ«tÄ«ba paliek nemainÄ«ga: Datu daļas saņemÅ”ana un kopējās summas saskaitÄ«Å”ana ir divi principiāli atŔķirÄ«gi pieprasÄ«jumi, un katram ir nepiecieÅ”ami savi optimizācijas pasākumi. Kopumā jÅ«s nevarēsit atrast indeksu kombināciju, kas vienlÄ«dz labi darbojas abiem vaicājumiem.

AttiecÄ«gi viena no bÅ«tiskām prasÄ«bām, kas bÅ«tu jāprecizē, izstrādājot Ŕādu meklÄ“Å”anas risinājumu, ir, vai uzņēmumam tieŔām ir svarÄ«gi redzēt kopējo atrasto objektu skaitu. Bieži gadās, ka nē. Un navigācija pēc konkrētiem lappuÅ”u numuriem, manuprāt, ir risinājums ar ļoti Å”auru darbÄ«bas jomu, jo vairums peidžeru scenāriju izskatās kā ā€œpāriet uz nākamo lapuā€.

Peidžeru opcija Nr. 2

Pieņemsim, ka lietotājiem nav svarÄ«gi zināt kopējo atrasto objektu skaitu. Mēģināsim vienkārÅ”ot meklÄ“Å”anas lapu:

MeklÄ“Å”anas rezultātu izvades un veiktspējas problēmas
Faktiski ir mainÄ«jies tikai tas, ka nav iespējams pārvietoties uz konkrētiem lapu numuriem, un tagad Å”ai tabulai nav jāzina, cik to var bÅ«t, lai to parādÄ«tu. Bet rodas jautājums - kā tabula zina, vai ir dati par nākamo lapu (lai pareizi parādÄ«tu saiti "Nākamais")?

Atbilde ir ļoti vienkārÅ”a: jÅ«s varat nolasÄ«t no datu bāzes par vienu ierakstu vairāk, nekā nepiecieÅ”ams attēloÅ”anai, un Ŕī ā€œpapilduā€ ieraksta klātbÅ«tne parādÄ«s, vai ir nākamā daļa. Tādā veidā jums ir nepiecieÅ”ams izpildÄ«t tikai vienu pieprasÄ«jumu, lai iegÅ«tu vienu datu lapu, kas ievērojami uzlabo veiktspēju un atvieglo Ŕādas funkcionalitātes atbalstu. Manā praksē bija gadÄ«jums, kad atteikÅ”anās skaitÄ«t kopējo ierakstu skaitu paātrina rezultātu piegādi 4-5 reizes.

Å ai pieejai ir vairākas lietotāja saskarnes opcijas: komandas "atpakaļ" un "uz priekÅ”u", tāpat kā iepriekÅ” minētajā piemērā, poga "ielādēt vairāk", kas vienkārÅ”i pievieno parādÄ«tajiem rezultātiem jaunu daļu, "bezgalÄ«ga ritināŔana", kas darbojas. pēc principa "ielādēt vairāk", bet signāls, lai iegÅ«tu nākamo daļu, ir lietotājam, lai ritinātu visus parādÄ«tos rezultātus lÄ«dz beigām. Lai kāds bÅ«tu vizuālais risinājums, datu izlases princips paliek nemainÄ«gs.

Peidžeru ievieŔanas nianses

Visos iepriekÅ” sniegtajos vaicājumu piemēros tiek izmantota pieeja ā€œnobÄ«de + skaitÄ«Å”anaā€, kad pats vaicājums norāda, kādā secÄ«bā ir jāatgriež rezultātu rindas un cik rindu ir jāatgriež. Vispirms apskatÄ«sim, kā Å”ajā gadÄ«jumā vislabāk organizēt parametru nodoÅ”anu. Praksē esmu sastapies ar vairākām metodēm:

  • PieprasÄ«tās lapas sērijas numurs (pageIndex), lapas izmērs (pageSize).
  • Pirmā atgriežamā ieraksta sērijas numurs (startIndex), maksimālais ierakstu skaits rezultātā (skaits).
  • Pirmā atgriežamā ieraksta kārtas numurs (startIndex), pēdējā atgriežamā ieraksta kārtas numurs (endIndex).

No pirmā acu uzmetiena var Ŕķist, ka tas ir tik elementāri, ka nav nekādas atŔķirÄ«bas. Bet tas tā nav - ērtākā un universālākā iespēja ir otrā (startIndex, count). Tam ir vairāki iemesli:

  • IepriekÅ” aprakstÄ«tajai +1 ieraksta korektÅ«ras pieejai pirmā opcija ar pageIndex un pageSize ir ārkārtÄ«gi neērta. Piemēram, mēs vēlamies parādÄ«t 50 ziņas vienā lapā. Saskaņā ar iepriekÅ” minēto algoritmu jums ir jāizlasa par vienu ierakstu vairāk nekā nepiecieÅ”ams. Ja Å”is ā€œ+1ā€ nav ieviests serverÄ«, izrādās, ka pirmajai lapai mums ir jāpieprasa ieraksti no 1 lÄ«dz 51, otrajai - no 51 lÄ«dz 101 utt. Ja norādāt lapas izmēru 51 un palielināsit pageIndex, tad otrā lapa atgriezÄ«sies no 52 uz 102 utt. AttiecÄ«gi pirmajā variantā vienÄ«gais veids, kā pareizi ieviest pogu, lai pārietu uz nākamo lapu, ir likt serverim pārbaudÄ«t ā€œpapilduā€ rindiņu, kas bÅ«s ļoti netieÅ”a nianse.
  • TreÅ”ajai opcijai vispār nav jēgas, jo, lai izpildÄ«tu vaicājumus lielākajā daļā datu bāzu, jums joprojām ir jānokārto skaitÄ«Å”ana, nevis pēdējā ieraksta indekss. StartIndex atņemÅ”ana no endIndex var bÅ«t vienkārÅ”a aritmētiska darbÄ«ba, taču Å”eit tā ir lieka.

Tagad mums jāapraksta peidžeru ievieÅ”anas trÅ«kumi, izmantojot ā€œnobÄ«de + daudzumsā€:

  • Katras nākamās lapas izgÅ«Å”ana bÅ«s dārgāka un lēnāka nekā iepriekŔējā, jo datu bāzei vēl bÅ«s jāiziet cauri visi ieraksti ā€œno sākumaā€ pēc meklÄ“Å”anas un kārtoÅ”anas kritērijiem un tad jāapstājas pie vēlamā fragmenta.
  • Ne visas DBVS var atbalstÄ«t Å”o pieeju.

Ir alternatÄ«vas, taču tās ir arÄ« nepilnÄ«gas. Pirmo no Ŕīm pieejām sauc par ā€œatslēgkopu peidžeruā€ vai ā€œmeklÄ“Å”anas metodiā€, un tā ir Ŕāda: pēc daļas saņemÅ”anas varat atcerēties lauku vērtÄ«bas lapas pēdējā ierakstā un pēc tam izmantot tās, lai iegÅ«tu nākamā porcija. Piemēram, mēs izpildÄ«jām Ŕādu vaicājumu:

SELECT * FROM Sales.SalesOrderHeader
ORDER BY OrderDate DESC
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY

Un pēdējā ierakstā mēs saņēmām pasÅ«tÄ«juma datuma vērtÄ«bu ā€˜2014-06-29ā€™. Pēc tam, lai iegÅ«tu nākamo lapu, varat mēģināt rÄ«koties Ŕādi:

SELECT * FROM Sales.SalesOrderHeader
WHERE OrderDate < '2014-06-29'
ORDER BY OrderDate DESC
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY

Problēma ir tāda, ka OrderDate nav unikāls lauks, un iepriekÅ” norādÄ«tajā nosacÄ«jumā, iespējams, netiks rādÄ«ts daudz obligāto rindu. Lai Å”im vaicājumam pievienotu nepārprotamÄ«bu, nosacÄ«jumam jāpievieno unikāls lauks (pieņemsim, ka 75074 ir primārās atslēgas pēdējā vērtÄ«ba no pirmās daļas):

SELECT * FROM Sales.SalesOrderHeader
WHERE (OrderDate = '2014-06-29' AND SalesOrderID < 75074)
   OR (OrderDate < '2014-06-29')
ORDER BY OrderDate DESC, SalesOrderID DESC
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY

Å Ä« opcija darbosies pareizi, taču kopumā to bÅ«s grÅ«ti optimizēt, jo nosacÄ«jums satur operatoru VAI. Ja primārās atslēgas vērtÄ«ba palielinās, palielinoties OrderDate, nosacÄ«jumu var vienkārÅ”ot, atstājot tikai filtru pēc SalesOrderID. Bet, ja nav stingras korelācijas starp primārās atslēgas vērtÄ«bām un lauku, pēc kura tiek kārtots rezultāts, lielākajā daļā DBVS nevar izvairÄ«ties no Ŕī VAI. Izņēmums, par kuru es zinu, ir PostgreSQL, kas pilnÄ«bā atbalsta koreÅ”u salÄ«dzināŔanu, un iepriekÅ” minēto nosacÄ«jumu var rakstÄ«t kā "WHERE (OrderDate, SalesOrderID) < ('2014-06-29', 75074)". Ņemot vērā salikto atslēgu ar Å”iem diviem laukiem, Ŕādam vaicājumam vajadzētu bÅ«t diezgan vienkārÅ”am.

Otru alternatÄ«vu pieeju var atrast, piemēram, ElasticSearch ritināŔanas API vai Cosmos DB ā€” ja pieprasÄ«jums papildus datiem atgriež Ä«paÅ”u identifikatoru, ar kuru jÅ«s varat iegÅ«t nākamo datu daļu. Ja Å”im identifikatoram ir neierobežots kalpoÅ”anas laiks (kā Comsos DB), tad tas ir lielisks veids, kā ieviest peidžeru ar secÄ«gu pāreju starp lapām (iepriekÅ” minētā opcija Nr. 2). Tās iespējamie trÅ«kumi: tas netiek atbalstÄ«ts visās DBVS; iegÅ«tajam nākamā gabala identifikatoram var bÅ«t ierobežots kalpoÅ”anas laiks, kas parasti nav piemērots lietotāja mijiedarbÄ«bas ievieÅ”anai (piemēram, ElasticSearch ritināŔanas API).

Sarežģīta filtrÄ“Å”ana

Sarežģīsim uzdevumu vēl vairāk. Pieņemsim, ka ir prasÄ«ba ieviest tā saukto fasetēto meklÄ“Å”anu, kas ikvienam ir ļoti pazÄ«stama no interneta veikaliem. IepriekÅ” minētie piemēri, kuru pamatā ir pasÅ«tÄ«jumu tabula, Å”ajā gadÄ«jumā nav Ä«paÅ”i ilustratÄ«vi, tāpēc pāriesim uz tabulu Produkts no AdventureWorks datu bāzes:

MeklÄ“Å”anas rezultātu izvades un veiktspējas problēmas
Kāda ir Ŕķautņu meklÄ“Å”anas ideja? Fakts ir tāds, ka katram filtra elementam tiek parādÄ«ts Å”im kritērijam atbilstoÅ”o ierakstu skaits ņemot vērā visās pārējās kategorijās atlasÄ«tos filtrus.

Piemēram, ja Å”ajā piemērā atlasām kategoriju Velosipēdi un krāsu Melnu, tabulā tiks rādÄ«ti tikai melni velosipēdi, bet:

  • Katram kritērijam grupā Kategorijas preču skaits no Ŕīs kategorijas tiks parādÄ«ts melnā krāsā.
  • Katram grupas ā€œKrāsasā€ kritērijam tiks parādÄ«ts Ŕīs krāsas velosipēdu skaits.

Å eit ir Ŕādu apstākļu rezultātu izvades piemērs:

MeklÄ“Å”anas rezultātu izvades un veiktspējas problēmas
Ja atzÄ«mēsiet arÄ« kategoriju ā€œApģērbsā€, tabulā bÅ«s redzamas arÄ« melnas drēbes, kas ir noliktavā. ArÄ« melno preču skaits sadaļā ā€œKrāsaā€ tiks pārrēķināts pēc jaunajiem nosacÄ«jumiem, tikai sadaļā ā€œKategorijasā€ nekas nemainÄ«sies... Ceru, ka ar Å”iem piemēriem pietiks, lai saprastu ierasto faceted meklÄ“Å”anas algoritmu.

Tagad iedomāsimies, kā to var Ä«stenot uz attiecÄ«bu pamata. Katrai kritēriju grupai, piemēram, kategorijai un krāsai, bÅ«s nepiecieÅ”ams atseviŔķs vaicājums:

SELECT pc.ProductCategoryID, pc.Name, COUNT(1) FROM Production.Product p
  INNER JOIN Production.ProductSubcategory ps ON p.ProductSubcategoryID = ps.ProductSubcategoryID
  INNER JOIN Production.ProductCategory pc ON ps.ProductCategoryID = pc.ProductCategoryID
WHERE p.Color = 'Black'
GROUP BY pc.ProductCategoryID, pc.Name
ORDER BY COUNT(1) DESC

MeklÄ“Å”anas rezultātu izvades un veiktspējas problēmas

SELECT Color, COUNT(1) FROM Production.Product p
  INNER JOIN Production.ProductSubcategory ps ON p.ProductSubcategoryID = ps.ProductSubcategoryID
WHERE ps.ProductCategoryID = 1 --Bikes
GROUP BY Color
ORDER BY COUNT(1) DESC

MeklÄ“Å”anas rezultātu izvades un veiktspējas problēmas
Kas ir nepareizi ar Å”o risinājumu? Tas ir ļoti vienkārÅ”i ā€” tas nav labi mērogots. Katrai filtra sadaļai ir nepiecieÅ”ams atseviŔķs vaicājums, lai aprēķinātu daudzumus, un Å”ie vaicājumi nav no tiem vienkārŔākajiem. TieÅ”saistes veikalos dažās kategorijās var bÅ«t vairāki desmiti filtru sadaļu, kas var bÅ«t nopietna veiktspējas problēma.

Parasti pēc Å”iem apgalvojumiem man tiek piedāvāti daži risinājumi, proti:

  • Apvienojiet visus daudzumu uzskaites vienā vaicājumā. Tehniski tas ir iespējams, izmantojot atslēgvārdu UNION, taču tas daudz nepalÄ«dzēs veiktspējai - datu bāzei joprojām bÅ«s jāizpilda katrs fragments no nulles.
  • KeÅ”atmiņas daudzumi. Tas man tiek ieteikts gandrÄ«z katru reizi, kad aprakstu problēmu. BrÄ«dinājums ir tāds, ka tas parasti nav iespējams. Pieņemsim, ka mums ir 10 "Ŕķautnes", no kurām katrai ir 5 vērtÄ«bas. Å Ä« ir ļoti ā€œpieticÄ«gaā€ situācija, salÄ«dzinot ar to, ko var redzēt tajos paÅ”os interneta veikalos. Viena aspekta elementa izvēle ietekmē daudzumus 9 citos, citiem vārdiem sakot, katrai kritēriju kombinācijai daudzumi var bÅ«t atŔķirÄ«gi. MÅ«su piemērā kopā ir 50 kritēriji, kurus lietotājs var atlasÄ«t, tātad iespējamās kombinācijas bÅ«s 250. Nav pietiekami daudz atmiņas vai laika, lai aizpildÄ«tu Ŕādu datu masÄ«vu. Å eit var iebilst un teikt, ka ne visas kombinācijas ir Ä«stas un lietotājs reti izvēlas vairāk par 5-10 kritērijiem. Jā, ir iespējams veikt slinku ielādi un keÅ”atmiņā saglabāt tikai kādreiz atlasÄ«to daudzumu, taču, jo vairāk atlases bÅ«s, jo mazāk efektÄ«va bÅ«s Ŕāda keÅ”atmiņa un pamanāmākas bÅ«s reakcijas laika problēmas (Ä«paÅ”i, ja datu kopa regulāri mainās).

Par laimi, Ŕādai problēmai jau sen ir bijuÅ”i diezgan efektÄ«vi risinājumi, kas paredzami darbojas ar lielu datu apjomu. Jebkurai no Ŕīm opcijām ir jēga sadalÄ«t aspektu pārrēķinu un rezultātu lapas saņemÅ”anu divos paralēlos izsaukumos uz serveri un sakārtot lietotāja interfeisu tā, lai datu ielāde pa aspektiem ā€œnetraucēā€ MeklÄ“Å”anas rezultāti.

  • Pēc iespējas retāk izsauciet pilnÄ«gu ā€œÅ”Ä·autņuā€ pārrēķinu. Piemēram, nepārrēķiniet visu katru reizi, kad mainās meklÄ“Å”anas kritēriji, bet gan atrodiet kopējo rezultātu skaitu, kas atbilst paÅ”reizējiem nosacÄ«jumiem, un aiciniet lietotāju tos parādÄ«t - "Atrasti 1425 ieraksti, rādÄ«t?" Lietotājs var vai nu turpināt mainÄ«t meklÄ“Å”anas vienumus, vai arÄ« noklikŔķināt uz pogas ā€œrādÄ«tā€. Tikai otrajā gadÄ«jumā tiks izpildÄ«ti visi pieprasÄ«jumi iegÅ«t rezultātus un pārrēķināt daudzumus visās ā€œÅ”Ä·autnēsā€. Å ajā gadÄ«jumā, kā jÅ«s viegli varat redzēt, jums bÅ«s jārisina pieprasÄ«jums iegÅ«t kopējo rezultātu skaitu un tā optimizāciju. Å o metodi var atrast daudzos mazos tieÅ”saistes veikalos. AcÄ«mredzot Ŕī nav panaceja Å”ai problēmai, taču vienkārÅ”os gadÄ«jumos tas var bÅ«t labs kompromiss.
  • Izmantojiet meklētājprogrammas, lai atrastu rezultātus un saskaitÄ«tu aspektus, piemēram, Solr, ElasticSearch, Sphinx un citus. Visi no tiem ir paredzēti, lai izveidotu "Ŕķautnes", un to dara diezgan efektÄ«vi, pateicoties apgrieztajam indeksam. Kā darbojas meklētājprogrammas, kāpēc Ŕādos gadÄ«jumos tās ir efektÄ«vākas par vispārējas nozÄ«mes datubāzēm, kāda ir prakse un kļūmes ā€“ tā ir atseviŔķa raksta tēma. Å eit vēlos vērst jÅ«su uzmanÄ«bu uz to, ka meklētājprogramma nevar aizstāt galveno datu krātuvi, tā tiek izmantota kā papildinājums: visas izmaiņas galvenajā datubāzē, kas ir bÅ«tiskas meklÄ“Å”anai, tiek sinhronizētas meklÄ“Å”anas rādÄ«tājā; Meklētājprogramma parasti mijiedarbojas tikai ar meklētājprogrammu un nepiekļūst galvenajai datubāzei. Viens no svarÄ«gākajiem jautājumiem Å”eit ir tas, kā uzticami organizēt Å”o sinhronizāciju. Tas viss ir atkarÄ«gs no ā€œreakcijas laikaā€ prasÄ«bām. Ja laiks starp izmaiņām galvenajā datubāzē un to ā€œizpauÅ”anosā€ meklÄ“Å”anā nav kritisks, varat izveidot pakalpojumu, kas ik pēc dažām minÅ«tēm meklē nesen mainÄ«tos ierakstus un indeksē tos. Ja vēlaties pēc iespējas Ä«sāku reakcijas laiku, varat ieviest kaut ko lÄ«dzÄ«gu darÄ«jumu izsÅ«tne lai nosÅ«tÄ«tu atjauninājumus meklÄ“Å”anas pakalpojumam.

Atzinumi

  1. Servera puses peidžeru ievieÅ”ana ir ievērojama komplikācija, un tā ir jēga tikai strauji augoŔām vai vienkārÅ”i lielām datu kopām. Nav absolÅ«ti precÄ«zas receptes, kā novērtēt ā€œlieloā€ vai ā€œÄtri augoÅ”uā€, taču es izvēlētos Ŕādu pieeju:
    • Ja pilnÄ«gas datu kolekcijas saņemÅ”ana, ņemot vērā servera laiku un tÄ«kla pārraidi, parasti atbilst veiktspējas prasÄ«bām, nav jēgas ieviest peidžeru servera pusē.
    • Var rasties situācija, ka tuvākajā nākotnē nav gaidāmas veiktspējas problēmas, jo datu ir maz, bet datu apkopojums nepārtraukti pieaug. Ja kāda datu kopa nākotnē vairs neatbilst iepriekŔējam punktam, labāk ir nekavējoties sākt lapoÅ”anu.
  2. Ja uzņēmumam nav stingras prasÄ«bas parādÄ«t kopējo rezultātu skaitu vai parādÄ«t lappuÅ”u numurus, un jÅ«su sistēmā nav meklētājprogrammas, labāk neieviest Å”os punktus un apsvērt iespēju #2.
  3. Ja ir skaidra prasÄ«ba pēc slÄ«pētas meklÄ“Å”anas, jums ir divas iespējas, nezaudējot veiktspēju.
    • Nepārrēķiniet visus daudzumus katru reizi, kad mainās meklÄ“Å”anas kritēriji.
    • Izmantojiet meklētājprogrammas, piemēram, Solr, ElasticSearch, Sphinx un citas. Bet jāsaprot, ka tas nevar aizstāt galveno datubāzi, un tas ir jāizmanto kā papildinājums galvenajai krātuvei meklÄ“Å”anas problēmu risināŔanai.
  4. Turklāt slÄ«pētas meklÄ“Å”anas gadÄ«jumā ir lietderÄ«gi sadalÄ«t meklÄ“Å”anas rezultātu lapas izguvi un skaitÄ«Å”anu divos paralēlos pieprasÄ«jumos. Daudzumu skaitÄ«Å”ana var aizņemt ilgāku laiku nekā rezultātu iegÅ«Å”ana, savukārt rezultāti lietotājam ir svarÄ«gāki.
  5. Ja meklÄ“Å”anai izmantojat SQL datu bāzi, visas ar Å”o daļu saistÄ«tās koda izmaiņas ir rÅ«pÄ«gi jāpārbauda, ā€‹ā€‹vai tās darbojas atbilstoŔā datu daudzumā (pārsniedzot reāllaika datubāzes apjomu). Ieteicams arÄ« izmantot vaicājuma izpildes laika uzraudzÄ«bu visos datu bāzes gadÄ«jumos, un jo Ä«paÅ”i ā€œdzÄ«vajāā€. Pat ja izstrādes stadijā ar vaicājumu plāniem viss bija kārtÄ«bā, pieaugot datu apjomam, situācija var manāmi mainÄ«ties.

Avots: www.habr.com

Pievieno komentāru