sql >> Databasteknik >  >> RDS >> Mysql

MySQL-skärning närmar sig?

Det bästa sättet att skära MySQL-tabeller är att inte göra det om det inte är helt oundvikligt att göra det.

När du skriver en applikation vill du vanligtvis göra det på ett sätt som maximerar hastighet, utvecklarhastighet. Du optimerar för latens (tid tills svaret är klart) eller genomströmning (antal svar per tidsenhet) endast när det behövs.

Du partitionerar och tilldelar sedan partitioner till olika värdar (=shard) endast när summan av alla dessa partitioner inte längre passar in på en enda databasserverinstans - anledningen till det är antingen skrivning eller läsning.

Skrivfallet är antingen a) frekvensen av skrivningar överbelastas denna servers diskar permanent eller b) det pågår för många skrivningar så att replikeringen permanent släpar efter i denna replikeringshierarki.

Läsfallet för skärning är när storleken på data är så stor att arbetsuppsättningen av den inte längre passar in i minnet och dataläsningar börjar träffa disken istället för att serveras från minnet för det mesta.

Bara när du har att skära gör du det.

I det ögonblick du skär, betalar du för det på flera sätt:

Mycket av din SQL är inte längre deklarativ.

Normalt i SQL talar du om för databasen vilken data du vill ha och överlåter till optimeraren att förvandla den specifikationen till ett dataåtkomstprogram. Det är bra, eftersom det är flexibelt och för att skriva dessa dataåtkomstprogram är tråkigt arbete som skadar hastigheten.

Med en fragmenterad miljö sammanfogar du förmodligen en tabell på nod A mot data på nod B, eller så har du en tabell som är större än en nod, på nod A och B och sammanfogar data från den mot data som finns på nod B och C. Du börjar skriva hashbaserade anslutningsupplösningar på applikationssidan manuellt för att lösa det (eller så återuppfinner du MySQL-klustret), vilket innebär att du slutar med en hel del SQL som inte längre deklarativa, utan uttrycker SQL-funktionalitet på ett procedurmässigt sätt (t.ex. använder du SELECT-satser i loopar).

Du ådrar dig mycket nätverkslatens.

Normalt kan en SQL-fråga lösas lokalt och optimeraren känner till kostnaderna för lokala diskåtkomster och löser frågan på ett sätt som minimerar kostnaderna för det.

I en delad miljö löses frågor genom att antingen köra nyckel-värdeåtkomster över ett nätverk till flera noder (förhoppningsvis med batchnyckelåtkomster och inte individuella nyckeluppslagningar per tur och retur) eller genom att trycka på delar av WHERE klausulen vidare till noderna där de kan tillämpas (det kallas 'condition pushdown'), eller båda.

Men även i de bästa fallen innebär detta många fler nätverksresor än en lokal situation, och det är mer komplicerat. Speciellt eftersom MySQL-optimeraren inte vet något om nätverkslatens alls (Ok, MySQL-klustret blir sakta bättre på det, men för vanilla MySQL utanför klustret är det fortfarande sant).

Du förlorar mycket av SQLs uttryckskraft.

Ok, det är förmodligen mindre viktigt, men begränsningar för främmande nyckel och andra SQL-mekanismer för dataintegritet är oförmögna att spänna över flera skärvor.

MySQL har inget API som tillåter asynkrona frågor som fungerar.

När data av samma typ finns på flera noder (t.ex. användardata på nod A, B och C) måste horisontella frågor ofta lösas mot alla dessa noder ("Hitta alla användarkonton som inte har varit inloggade på 90 dagar eller mer"). Dataåtkomsttiden växer linjärt med antalet noder, såvida inte flera noder kan frågas parallellt och resultaten aggregeras när de kommer in ("Map-Reduce").

Förutsättningen för det är ett asynkron kommunikations-API, som inte finns för MySQL i ett bra fungerande skick. Alternativet är mycket splittring och kopplingar i barnprocesserna, vilket är att besöka suckvärlden på ett säsongskort.

När du väl börjar klippa blir datastrukturen och nätverkstopologin synliga som prestandapunkter för din applikation. För att prestera någorlunda bra måste din applikation vara medveten om dessa saker, och det betyder att det egentligen bara är applikationsnivåskärning som är vettigt.

Frågan är mer om du vill auto-shard (bestämma vilken rad som går in i vilken nod genom att hasha primärnycklar till exempel) eller om du vill dela upp funktionellt på ett manuellt sätt ("Tabellerna relaterade till xyz-användarberättelsen går till detta master, medan abc- och def-relaterade tabeller går till den mastern").

Funktionell skärning har fördelen att, om den görs rätt, är den osynlig för de flesta utvecklare för det mesta, eftersom alla tabeller relaterade till deras användarberättelse kommer att vara tillgängliga lokalt. Det gör att de fortfarande kan dra nytta av deklarativ SQL så länge som möjligt, och kommer också att medföra mindre nätverkslatens eftersom antalet överföringar över nätverk hålls minimalt.

Funktionell skärning har nackdelen att den inte tillåter att någon tabell är större än en instans, och det kräver manuell uppmärksamhet av en designer.

Funktionell skärning har fördelen att det relativt enkelt görs till en befintlig kodbas med ett antal ändringar som inte är alltför stora. http://Booking.com har gjort det flera gånger under de senaste åren och det fungerade bra för dem.

Efter att ha sagt allt detta, när jag tittar på din fråga, tror jag att du ställer fel frågor, eller så missförstår jag helt ditt problemformulering.



  1. Skapa en tillfällig tabell baserad på en annan tabell i SQL Server

  2. Dålig standby

  3. Hantera transaktioner samtidigt med lås i SQL Server

  4. Vad gör en transaktion kring ett enskilt uttalande?