sql >> Databasteknik >  >> RDS >> Mysql

Varför ger InnoDB uppenbarligen falsk information om ledigt utrymme

(Detta svarar på några av frågorna begravda i kommentarer.)

Felbenämning "Fritt" utrymme inkluderar bara hela block, inte extra utrymme inuti block, och många andra detaljer.

Fall 1:Alla tabeller finns i ibdata1 -- SHOW TABLE STATUS (eller motsvarande fråga i information_schema kommer att visa samma Data_free värde, nämligen hur mycket som är ledigt i ibdata1 . Detta utrymme kan återanvändas av vilket bord som helst. Det är svårt att ge tillbaka utrymmet till operativsystemet.

Fall 2:Alla tabeller är file_per_table -- Nu är varje Data_free hänvisar till utrymmet för bordet. Och SUM() är meningsfullt. (ibdata1 finns fortfarande, men den innehåller inga riktiga tabeller; det finns mycket annat som InnoDB behöver.)

Fall 3:Blandning -- Om du slår på/av file_per_table vid olika tidpunkter, kommer vissa tabeller att finnas i ibdata1, vissa kommer att ha sina egna tabellutrymmen.

Fall 4:SKAPA TABLESPACE i 5.7 -- Du kan till exempel ha ett tabellutrymme för varje databas.

Fall 5:PARTITIONERADE tabeller -- Varje partition fungerar som en tabell.

Fall 6:8.0 -- Ännu fler förändringar kommer.

Databas ==Katalog I MySQL:s katalogträd kan varje databas ses som en filsystemkatalog. Inom den katalogen kan man se en uppsättning filer för varje tabell. .frm filen innehåller tabelldefinitionen. Om en .ibd filen finns, tabellen skapades med file_per_table. Detta kan vara det mest tillförlitliga sättet att upptäcka om tabellen är file_per_table. (8.0 kommer att ha betydande förändringar här.)

Hur mycket utrymme kan jag återanvända ? Det finns inget bra svar. Vanligtvis kommer att infoga en rad hitta utrymme i blocket där den hör hemma, och Data_free kommer inte att krympa. Men om det fanns blockuppdelning(ar), kan Data_free sjunka med någon multipel av 16KB (blockstorleken) eller 4MB ("omfattningsstorleken" - eller kanske är det 8MB?). Dessutom leder slumpmässiga insättningar till att BTree-blocken är i genomsnitt cirka 69 % fulla.

Ändra innodb_file_per_table har ingen effekt förrän nästa CREATE TABLE eller ALTER TABLE . Och då har det bara effekt på var du ska placera de nyskapade/kopierade data+indexen (ibdata1 eller .ibd). Det kommer inte att förstöra data.

Stora bord har vanligtvis 4MB till 7MB Data_free. När du beräknar hur många rader du kan lägga till, planera inte att Data_free hamnar under det intervallet.

Avg_row_size borde vara användbart. Men ibland är det (och rader) dåligt approximerade. Deras produkt (Data_length) är alltid korrekt. Så det här kan vara en bra uppskattning av "rader att gå innan du tar mer utrymme från OS:

(Data_free - 7M) / Avg_row_size

Rekommendationer för bordsutrymme :Sätt "stora" tabeller i file_per_table. Sätt "små" tabeller i ibdata1 eller databasspecifika tabellutrymmen (5.7). Tyvärr, ingen enkel rekommendation på skiljelinjen mellan "stor" och "liten". Och det är klumpigt att migrera en tabell:SET global innodb_file_per_table = ...;; logga ut; logga in (för att hämta den globala); ALTER TABLE tbl ENGINE=InnoDB; . Och det är nödvändigtvis en fullständig kopia av tabellen.

(Varning :Jag har utelämnat många detaljer.)



  1. Är det bättre att VÄLJA innan du GÅR MED?

  2. konstiga karaktärer som ‪ ‬ ‏

  3. är det möjligt att välja FINNS direkt som lite?

  4. Oracle Pl/SQL:Slinga genom XMLTYPE-noder