sql >> Database teknologi >  >> RDS >> Mysql

MySQL-sharding nærmer sig?

Den bedste metode til at sønderdele MySQL-tabeller er ikke at gøre det, medmindre det er helt uundgåeligt at gøre det.

Når du skriver en applikation, vil du normalt gøre det på en måde, der maksimerer hastigheden, udviklerhastigheden. Du optimerer kun for latenstid (tid indtil svaret er klar) eller gennemløb (antal svar pr. tidsenhed), når det er nødvendigt.

Du partitionerer og tildeler derefter partitioner til forskellige værter (=shard), når summen af ​​alle disse partitioner ikke længere passer ind på en enkelt databaseserverinstans - grunden til det er enten skrivning eller læsning.

Skrivetilfældet er enten a) frekvensen af ​​skrivninger overbelaster denne servers diske permanent eller b) der er for mange skrivninger i gang, så replikeringen halter permanent i dette replikeringshierarki.

Læsecasen for sharding er, når størrelsen af ​​data er så stor, at arbejdssættet af det ikke længere passer ind i hukommelsen, og datalæsninger begynder at ramme disken i stedet for at blive serveret fra hukommelsen det meste af tiden.

Kun når du har at sønderdele du gør det.

I det øjeblik du skærer, betaler du for det på flere måder:

Meget af din SQL er ikke længere deklarativ.

Normalt fortæller du databasen i SQL, hvilke data du ønsker, og overlader det til optimeringsværktøjet at omdanne denne specifikation til et dataadgangsprogram. Det er en god ting, fordi det er fleksibelt, og fordi at skrive disse dataadgangsprogrammer er kedeligt arbejde, der skader hastigheden.

Med et sharded miljø forbinder du sandsynligvis en tabel på node A mod data på node B, eller du har en tabel, der er større end en node, på node A og B og forbinder data fra den mod data, der er på node B og C. Du begynder at skrive hash-baserede join-opløsninger på applikationssiden manuelt for at løse det (eller du genopfinder MySQL-klyngen), hvilket betyder, at du ender med en masse SQL, der ikke længere er deklarativ, men som udtrykker SQL-funktionalitet på en proceduremæssig måde (du bruger f.eks. SELECT-sætninger i loops).

Du pådrager dig meget netværksforsinkelse.

Normalt kan en SQL-forespørgsel løses lokalt, og optimeringsværktøjet kender til omkostningerne forbundet med lokal diskadgang og løser forespørgslen på en måde, der minimerer omkostningerne for det.

I et sharded miljø løses forespørgsler ved enten at køre nøgleværdiadgange på tværs af et netværk til flere noder (forhåbentlig med batchede nøgleadgange og ikke individuelle nøgleopslag pr. rundrejse) eller ved at skubbe dele af WHERE klausul videre til noderne, hvor de kan anvendes (det kaldes 'condition pushdown'), eller begge dele.

Men selv i de bedste tilfælde involverer dette mange flere netværksrejser end en lokal situation, og det er mere kompliceret. Især da MySQL-optimeringsværktøjet slet ikke ved noget om netværksforsinkelse (Ok, MySQL-klyngen bliver langsomt bedre til det, men for vanilla MySQL uden for klyngen er det stadig sandt).

Du mister en masse udtrykskraft i SQL.

Ok, det er nok mindre vigtigt, men fremmednøglebegrænsninger og andre SQL-mekanismer til dataintegritet er ude af stand til at spænde over flere shards.

MySQL har ingen API, som tillader asynkrone forespørgsler, der fungerer.

Når data af samme type findes på flere noder (f.eks. brugerdata på noderne A, B og C), skal vandrette forespørgsler ofte løses mod alle disse noder ("Find alle brugerkonti, der ikke har været logget ind i 90 dage eller mere"). Dataadgangstiden vokser lineært med antallet af noder, medmindre flere noder kan spørges parallelt og resultaterne aggregeres, efterhånden som de kommer ind ("Map-Reduce").

Forudsætningen for det er et asynkron kommunikations-API, som ikke eksisterer for MySQL i en god arbejdsform. Alternativet er en masse forgrening og forbindelser i børneprocesserne, som er at besøge suttens verden på et sæsonkort.

Når du begynder at sharding, bliver datastruktur og netværkstopologi synlige som ydelsespunkter til din applikation. For at yde nogenlunde godt, skal din applikation være opmærksom på disse ting, og det betyder, at kun applikationsniveau-sharding giver mening.

Spørgsmålet er mere, om du vil auto-shard (bestemme, hvilken række der går ind i hvilken node ved f.eks. at hashing primærnøgler), eller om du vil opdele funktionelt på en manuel måde ("tabellerne relateret til xyz-brugerhistorien går til denne master, mens abc- og def-relaterede tabeller går til den master").

Funktionel sharding har den fordel, at hvis det gøres rigtigt, er det usynligt for de fleste udviklere det meste af tiden, fordi alle tabeller relateret til deres brugerhistorie vil være tilgængelige lokalt. Det giver dem mulighed for stadig at drage fordel af deklarativ SQL så længe som muligt, og det vil også medføre mindre netværksforsinkelse, fordi antallet af overførsler på tværs af netværk holdes minimalt.

Funktionel sharding har den ulempe, at den ikke tillader, at et enkelt bord er større end én instans, og det kræver manuel opmærksomhed fra en designer.

Funktionel sharding har den fordel, at det relativt nemt gøres til en eksisterende kodebase med en række ændringer, der ikke er alt for store. http://Booking.com har gjort det flere gange i de seneste år, og det fungerede godt for dem.

Når alt det er sagt, når jeg ser på dit spørgsmål, tror jeg, at du stiller de forkerte spørgsmål, eller også misforstår jeg fuldstændig din problemformulering.



  1. Tips til bedre databasedesign

  2. Sådan opdeles en kommasepareret værdi i kolonner

  3. Jeg prøver at kopiere en fil, men får fejlmeddelelse

  4. Der kunne ikke oprettes forbindelse, fordi målmaskinen aktivt nægtede det (PHP / WAMP)