Mysql
 sql >> Base de données >  >> RDS >> Mysql

Pourquoi InnoDB donne-t-il de fausses informations sur l'espace libre ?

(Cela répond à certaines des questions enfouies dans les commentaires.)

Fausse appellation L'espace "libre" ne comprend que des blocs entiers, pas d'espace disponible à l'intérieur des blocs, et de nombreux autres détails.

Cas 1 :Toutes les tables sont dans ibdata1 -- SHOW TABLE STATUS (ou la requête équivalente dans information_schema affichera le même Data_free valeur, à savoir combien est libre dans ibdata1 . Cet espace peut être réutilisé par n'importe quelle table. Il est difficile de redonner de l'espace au système d'exploitation.

Cas 2 :Toutes les tables sont file_per_table -- Maintenant, chaque Data_free fait référence à l'espace pour la table. Et la SUM() est significatif. (ibdata1 existe toujours, mais il ne contient pas de vraies tables ; il y a beaucoup d'autres choses dont InnoDB a besoin.)

Cas 3 :Mélange -- Si vous activez/désactivez file_per_table à différents moments, certaines tables seront dans ibdata1, d'autres auront leurs propres tablespaces.

Cas 4 :CRÉER UN TABLESPACE dans la version 5.7 -- Par exemple, vous pouvez avoir un tablespace pour chaque base de données.

Cas 5 :tables partitionnées -- Chaque partition agit comme une table.

Cas 6 :8.0 -- Encore plus de changements sont à venir.

Base de données ==Répertoire Dans l'arborescence de répertoires de MySQL, chaque base de données peut être considérée comme un répertoire de système de fichiers. Dans ce répertoire, on peut voir un ensemble de fichiers pour chaque table. Le .frm Le fichier contient la définition de la table. Si un .ibd fichier existe, la table a été créée avec file_per_table. C'est peut-être le moyen le plus fiable de découvrir si la table est file_per_table. (8.0 aura des changements significatifs ici.)

Combien d'espace puis-je réutiliser ? Il n'y a pas de bonne réponse. Habituellement, l'insertion d'une ligne trouvera de l'espace dans le bloc auquel elle appartient, et Data_free ne rétrécira pas. Mais, s'il y avait des fractionnements de blocs, Data_free peut chuter d'un multiple de 16 Ko (la taille du bloc) ou de 4 Mo (la "taille de l'étendue" - ou peut-être est-ce 8 Mo ?). De plus, les insertions aléatoires conduisent à ce que les blocs BTree soient, en moyenne, remplis à environ 69 %.

Modification de innodb_file_per_table n'a aucun effet jusqu'au prochain CREATE TABLE ou ALTER TABLE . Et puis cela n'a d'effet que sur l'endroit où placer les données + index nouvellement créés/copiés (ibdata1 ou .ibd). Il ne détruira pas les données.

Grandes tables ont généralement 4 Mo à 7 Mo de Data_free. Lorsque vous calculez le nombre de lignes que vous pouvez ajouter, ne prévoyez pas que Data_free tombe en dessous de cette plage.

Avg_row_size devrait être utile. Mais parfois, il (et les lignes) sont mal approximés. Leur produit (Data_length) est toujours correct. Donc, cela pourrait être une bonne estimation des "lignes à parcourir avant de récupérer plus d'espace sur le système d'exploitation :

(Data_free - 7M) / Avg_row_size

Recommandations d'espace de table :Placer les 'grandes' tables dans file_per_table. Placez des tables "minuscules" dans ibdata1 ou des espaces de table spécifiques à la base de données (5.7). Désolé, pas de recommandation simple sur la ligne de démarcation entre "grand" et "petit". Et c'est maladroit de migrer une table :SET global innodb_file_per_table = ...;; Se déconnecter; login (pour récupérer le global); ALTER TABLE tbl ENGINE=InnoDB; . Et il s'agit nécessairement d'une copie intégrale du tableau.

(Mise en garde :J'ai omis de nombreux détails.)