Optimering av databassökningar med B2B-tjÀnst för byggare som exempel

Hur kan man öka antalet databasfrÄgor med tio gÄnger utan att byta till en kraftfullare server och ÀndÄ behÄlla systemets funktionalitet? Jag ska berÀtta hur vi kÀmpade mot minskad prestanda i vÄr databas, hur vi optimerade SQL-frÄgor för att betjÀna sÄ mÄnga anvÀndare som möjligt utan att öka kostnaderna för berÀkningsresurser.

Jag skapar en tjĂ€nst för hantering av affĂ€rsprocesser för byggföretag. Cirka 3 000 företag arbetar med oss. Mer Ă€n 10 000 personer arbetar varje dag med vĂ„rt system i 4-10 timmar. Det löser olika uppgifter inom planering, avisering, varning, validering
 Vi anvĂ€nder PostgreSQL 9.6. I databasen har vi cirka 300 tabeller och varje dag fĂ„r vi upp till 200 miljoner frĂ„gor (10 000 olika). I genomsnitt har vi 3-4 000 frĂ„gor per sekund, under de mest aktiva stunderna över 10 000 frĂ„gor per sekund. Majoriteten av frĂ„gorna Ă€r OLAP. TillĂ€gg, modifieringar och borttagningar Ă€r mycket fĂ€rre, sĂ„ OLTP-belastningen Ă€r relativt liten. Jag gav dessa siffror sĂ„ att ni kan bedöma omfattningen av vĂ„rt projekt och förstĂ„ hur vĂ„r erfarenhet kan vara anvĂ€ndbar för er.

Första bilden. Lyrisk

NÀr vi började utveckla, tÀnkte vi inte sÀrskilt mycket pÄ vilken belastning som skulle ligga pÄ databasen och vad vi skulle göra om servern slutade fungera. Vid utformningen av databasen följde vi allmÀnna rekommendationer och försökte undvika att skjuta oss sjÀlva i foten, men lÀngre Àn sÄ gick vi inte i rÄd som "anvÀnd inte mönstret Entity Attribute Values Vi gick inte. Vi designade utifrÄn normaliseringsprinciperna för att undvika dataduplicering och brydde oss inte om att pÄskynda vissa frÄgor. NÀr de första anvÀndarna kom, stötte vi pÄ prestandaproblem. Som vanligt var vi helt oförberedda för detta. De första problemen var enkla. I allmÀnhet löstes allt genom att lÀgga till en ny index. Men det kom en tid dÄ enkla lappar slutade fungera. NÀr vi insÄg att vi saknade erfarenhet och att det blev allt svÄrare att förstÄ vad problemen berodde pÄ, anlitade vi specialister som hjÀlpte oss att korrekt konfigurera servern, ansluta övervakning, och visade oss vart vi skulle titta för att fÄ statistik..

Andra bilden. Statistik

Vi har ungefÀr 10 000 olika förfrÄgningar som körs pÄ vÄr databas varje dag. Av dessa 10 000 finns det stora förfrÄgningar som körs 2-3 miljoner gÄnger med en genomsnittlig körningstid pÄ 0,1-0,3 ms, och sÄ finns det förfrÄgningar med en genomsnittlig körningstid pÄ 30 sekunder som anropas 100 gÄnger om dagen.

Det var inte möjligt att optimera alla 10 000 förfrÄgningar, sÄ vi beslutade att ta reda pÄ hur vi skulle rikta vÄra insatser för att korrekt öka databasens prestanda. Efter flera iterationer började vi dela upp förfrÄgningarna i typer.

TOP-förfrÄgningar

Dessa Àr de tyngsta förfrÄgningarna som tar mest tid (total tid). Det Àr förfrÄgningar som antingen anropas mycket ofta eller som tar mycket lÄng tid att genomföra (lÄnga och frekventa förfrÄgningar har redan optimerats under de första iterationerna i jakten pÄ hastighet). Totalt spenderar servern mest tid pÄ att exekvera dem. Det Àr ocksÄ viktigt att separera toppförfrÄgningarna efter total exekveringstid och separat efter IO-tid. SÀtten att optimera sÄdana förfrÄgningar Àr nÄgot olika.

Det Àr vanlig praxis för alla företag att arbeta med TOP-förfrÄgningarna. De Àr fÄ, och Àven optimering av en enda förfrÄgan kan frigöra 5-10% av resurserna. Men ju mer projektet "vÀxer", desto mer okomplicerad blir optimeringen av TOP-förfrÄgningarna. Alla enkla metoder Àr redan utförda, och den mest "tunga" förfrÄgan tar "bara" 3-5% av resurserna. Om TOP-förfrÄgningarna totalt tar mindre Àn 30-40% av tiden, har du förmodligen redan anstrÀngt dig för att de ska fungera snabbt, och det Àr dags att gÄ vidare till optimering av förfrÄgningar i nÀsta grupp.
FrÄgan kvarstÄr: hur mÄnga toppförfrÄgningar ska inkluderas i den hÀr gruppen? Jag brukar ta minst 10, men inte fler Àn 20. Jag försöker se till att tiden för den första och sista i TOP-gruppen inte skiljer sig mer Àn 10 gÄnger. SÄ om körningstiden för förfrÄgningarna faller kraftigt frÄn plats 1 till 10, sÄ tar jag TOP-10; om nedgÄngen Àr mer gradvis, ökar jag gruppens storlek till 15 eller 20.
Optimering av databassökningar med B2B-tjÀnst för byggare som exempel

Medel (medium)

Detta Àr alla förfrÄgningar som kommer direkt efter TOP, med undantag för de senaste 5-10%. Vanligtvis ligger möjligheten att avsevÀrt öka serverns prestanda i optimeringen av just dessa förfrÄgningar. Dessa förfrÄgningar kan utgöra upp till 80%. Men Àven om deras andel har överskridit 50%, betyder det att det Àr dags att titta noggrannare pÄ dem.

Svansen (tail)

Som nÀmnts, dessa förfrÄgningar ligger i slutet och tar upp 5-10 % av tiden. Man kan glömma dem, endast om man inte anvÀnder automatiska analysverktyg för förfrÄgningar, dÄ kan deras optimering ocksÄ göras billigt.

Hur bedömer man varje grupp?

Jag anvÀnder en SQL-frÄga som hjÀlper till att göra en sÄdan bedömning för PostgreSQL (jag Àr sÀker pÄ att man kan skriva en liknande frÄga för mÄnga andra databashanteringssystem).

SQL-frÄga för att bedöma storleken pÄ TOP-MEDIUM-TAIL grupper

SELECT sum(time_top) AS sum_top, sum(time_medium) AS sum_medium, sum(time_tail) AS sum_tail
FROM
(
  SELECT CASE WHEN rn  20 AND rn  800 THEN tt_percent ELSE 0 END AS time_tail
  FROM (
    SELECT total_time / (SELECT sum(total_time) FROM pg_stat_statements) * 100 AS tt_percent, query,
    ROW_NUMBER () OVER (ORDER BY total_time DESC) AS rn
    FROM pg_stat_statements
    ORDER BY total_time DESC
  ) AS t
)
AS ts

FrÄgeresultatet bestÄr av tre kolumner, var och en innehÄller procentandelen av tiden som gÄr Ät till att behandla förfrÄgningar frÄn denna grupp. Inom frÄgan finns tvÄ siffror (i mitt fall Àr det 20 och 800) som skiljer förfrÄgningar frÄn en grupp till en annan.

SÄ hÀr relaterar andelarna av förfrÄgningar vid början av optimeringsarbetet och nu.

Optimering av databassökningar med B2B-tjÀnst för byggare som exempel

Diagrammet visar att andelen TOP-förfrÄgningar har minskat kraftigt, medan "medel" har ökat.
Till en början inkluderade TOP-förfrÄgningar uppenbara misstag. Med tiden försvann barnsjukdomarna, andelen TOP-förfrÄgningar minskade, och det krÀvdes allt mer anstrÀngning för att snabba upp de tunga förfrÄgningarna.

För att fÄ texten av förfrÄgningarna anvÀnder vi följande frÄga

SELECT * FROM (
  SELECT ROW_NUMBER () OVER (ORDER BY total_time DESC) AS rn, total_time / (SELECT sum(total_time) FROM pg_stat_statements) * 100 AS tt_percent, query
  FROM pg_stat_statements
  ORDER BY total_time DESC
) AS T
WHERE
rn  20 AND rn  800  -- TAIL

HÀr Àr en lista över de mest anvÀnda metoderna som hjÀlpte oss att snabba upp TOP-förfrÄgningar:

  • Omdesign av systemet, till exempel omarbetning av logiken för aviseringar till en meddelandebroker istĂ€llet för periodiska förfrĂ„gningar till databasen.
  • LĂ€gg till eller Ă€ndra index.
  • Omarbeta ORM-förfrĂ„gningar till ren SQL.
  • Omarbeta logiken för lazy laddning av data.
  • Caching genom denormalisering av data. Till exempel har vi en koppling mellan tabellerna Leverans -> Faktura -> FörfrĂ„gning -> Ansökan. Det vill sĂ€ga varje leverans Ă€r kopplad till en ansökan genom andra tabeller. För att inte koppla alla tabeller i varje förfrĂ„gning duplicerade vi kopplingen till ansökan i tabellen Leverans.
  • Caching av statiska tabeller med referenser och sĂ€llan förĂ€ndrade tabeller i programmets minne.

Ibland krÀvde förÀndringar en betydande redesign, men gav en avlastning pÄ 5-10% av systemet och var berÀttigade. Med tiden blev vinsten allt mindre och redesignen blev allt mer omfattande.

DÄ uppmÀrksammade vi den andra gruppen av förfrÄgningar - gruppen av medelstora. Det fanns betydligt fler förfrÄgningar i den och det verkade som om en analys av hela gruppen skulle ta vÀldigt mycket tid. Men de flesta förfrÄgningarna visade sig vara vÀldigt enkla att optimera, och mÄnga problem Äterkom i olika varianter. HÀr Àr exempel pÄ nÄgra typiska optimeringar som vi tillÀmpade pÄ tiotals liknande förfrÄgningar och varje grupp av optimerade förfrÄgningar avlastade databasen med 3-5%.

  • IstĂ€llet för att kontrollera förekomsten av poster med COUNT och full skanning av tabellen började vi anvĂ€nda EXISTS.
  • Vi avskaffade DISTINCT (det finns ingen allmĂ€n lösning, men ibland kan man enkelt bli av med det och snabba upp förfrĂ„gan 10-100 gĂ„nger).

    Till exempel, istÀllet för en förfrÄgan för att hÀmta alla förare frÄn en stor leveransdatabas (DELIVERY)

    SELECT DISTINCT P.ID, P.FIRST_NAME, P.LAST_NAME
    FROM DELIVERY D JOIN PERSON P ON D.DRIVER_ID = P.ID
    

    gjorde vi en förfrÄgan mot en jÀmförelsevis liten tabell PERSON

    SELECT P.ID, P.FIRST_NAME, P.LAST_NAME
    FROM PERSON
    WHERE EXISTS(SELECT D.ID FROM DELIVERY WHERE D.DRIVER_ID = P.ID)
    

    Det verkade som om vi anvÀnde en korrelerad subfrÄga, men den ger en snabbare körning pÄ mer Àn 10 gÄnger.

  • I mĂ„nga fall avstod vi helt frĂ„n COUNT och
    ersatte det med en berÀkning av ett approximativt vÀrde.
  • istĂ€llet för
    UPPER(s) LIKE JOHN% 
    

    VPS KVM.

    s ILIKE "John%"
    

Varje specifik förfrÄgan lyckades vi pÄ vissa sÀtt accelerera med 3-1000 gÄnger. Trots de imponerande resultaten, trodde vi först att det inte fanns nÄgot syfte med att optimera en förfrÄgan som utförs pÄ 10 ms, som ligger i den tredje hundradet av de tyngsta förfrÄgningarna och som totalt sett bara utgör brÄkdelar av procenten av databassbelastningen. Men genom att tillÀmpa samma recept pÄ en grupp av liknande förfrÄgningar ÄterhÀmtade vi flera procent. För att slippa spendera tid pÄ manuell granskning av alla hundratals förfrÄgningar skrev vi nÄgra enkla skript som med hjÀlp av reguljÀra uttryck identifierade liknande förfrÄgningar. Slutligen gjorde den automatiska sökningen efter grupper av förfrÄgningar att vi ytterligare kunde förbÀttra vÄr prestanda med blygsamma insatser.

Resultatet Àr att vi redan har arbetat med samma hÄrdvara i tre Är. Den genomsnittliga belastningen ligger runt 30%, och under toppar gÄr den upp till 70%. Antalet förfrÄgningar och anvÀndare har ökat ungefÀr tio gÄnger. Och allt detta tack vare vÄrt stÀndiga övervakande av dessa grupper av förfrÄgningar TOP-MEDIUM. SÄ snart en ny förfrÄgan dyker upp i TOP-gruppen analyserar vi den genast och försöker snabbare. MEDIUM-gruppen granskas en gÄng i veckan med hjÀlp av skript för förfrÄgningsanalys. Om vi hittar nya förfrÄgningar som vi redan vet hur vi ska optimera, Àndrar vi dem snabbt. Ibland hittar vi nya sÀtt att optimera som kan tillÀmpas direkt pÄ flera förfrÄgningar.

Enligt vÄra prognoser kan den nuvarande servern hantera en ökning av antalet anvÀndare med ytterligare 3-5 gÄnger. Men vi har ocksÄ ett ess i rockÀrmen - vi har fortfarande inte flyttat SELECT-förfrÄgningarna till spegeln, som rekommenderas. Men vi gör inte det medvetet, eftersom vi vill först helt utnyttja möjligheterna för "smart" optimering innan vi sÀtter in "tyngre artilleri".
En kritisk granskning av det utförda arbetet kan föreslÄ att man anvÀnder vertikal skalning. Att köpa en kraftfullare server istÀllet för att lÄta specialister slösa tid. En server kan kosta ganska lite, sÀrskilt eftersom vÄra grÀnser för vertikal skalning fortfarande inte har utnyttjats. Men antalet förfrÄgningar har ökat tio gÄnger. Under Ären har systemets funktionalitet ökat och nu finns det fler typer av förfrÄgningar. Den funktionalitet som fanns, utförs tack vare cachen med fÀrre, men mer effektiva förfrÄgningar. Det betyder att vi kan multiplicera med fem för att fÄ den verkliga hastighetsökningen. SÄ enligt de mest blygsamma berÀkningarna kan man sÀga att hastighetsökningen har varit 50 gÄnger eller mer. Att vertikalt uppgradera servern 50 gÄnger skulle kosta mer. SÀrskilt med tanke pÄ att en gÄng utförd optimering fungerar hela tiden, medan fakturan för den hyrda servern kommer varje mÄnad.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster