J'ai une base de données ayant un certain nombre de tables.
Je souhaite supprimer certains enregistrements des tableaux, car le nombre d'enregistrements dépasse 20 000 ou 50 000.
Toutes les tables sont InnoDB. Et file_per_table
est désactivé.
Lorsque je supprimerai les enregistrements d'un certain nombre de tables, il y aura une fragmentation dans les tables.
Existe-t-il un moyen de supprimer la fragmentation.?
Mise à jour le 17 avril
mysql> select TABLE_NAME, TABLE_SCHEMA, Data_free from information_schema.TABLES where TABLE_SCHEMA NOT IN ('information_schema', 'mysql') and Data_Free >0;
+-----------------+--------------+-----------+
| TABLE_NAME | TABLE_SCHEMA | Data_free |
+-----------------+--------------+-----------+
| City | world_innodb | 5242880 |
| City_Copy | world_innodb | 5242880 |
| Country | world_innodb | 5242880 |
| CountryLanguage | world_innodb | 5242880 |
| a | world_innodb | 5242880 |
| t1 | world_innodb | 5242880 |
| t2 | world_innodb | 5242880 |
+-----------------+--------------+-----------+
7 rows in set (0.00 sec)
Alors maintenant, ma question est de savoir comment je déciderai que mes tables sont fragmentées ou non.
J'ai résolu ce problème dans StackOverflow en octobre 2010 .
Gardez à l'esprit le fichier le plus occupé de l'infrastructure InnoDB:/var/lib/mysql/ibdata1
Ce fichier contient normalement quatre types d'informations
Fonctionnement OPTIMIZE TABLE
par rapport à une table InnoDB stockée dans ibdata1 fait deux choses:
Bien que vous puissiez séparer les données de table et les index de table d'ibdata1 et les gérer indépendamment en utilisant innodb_file_per_table , le grand espace béant de ibdata1 ne disparaîtra tout simplement pas et ne pourra pas être récupéré. Vous devez en faire plus.
Pour réduire une fois pour toutes ibdata1 vous devez procéder comme suit:
1) MySQLDump toutes les bases de données dans un fichier texte SQL (appelez-le /root/SQLData.sql)
2) Supprimez toutes les bases de données (sauf le schéma mysql)
3) Arrêtez mysql
4) Ajoutez les lignes suivantes à /etc/my.cnf
[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G
Sidenote: Quel que soit votre ensemble pour innodb_buffer_pool_size, assurez-vous que innodb_log_file_size représente 25% de innodb_buffer_pool_size.
5) Supprimer ibdata1, ib_logfile0 et ib_logfile1
À ce stade, il ne devrait y avoir que le schéma mysql dans/var/lib/mysql
6) Redémarrez mysql
Cela recréera ibdata1 à 10 ou 18 Mo (selon la version de MySQL), ib_logfile0 et ib_logfile1 à 1G chacun
7) Rechargez /root/SQLData.sql dans mysql
ibdata1 augmentera mais ne contiendra que des métadonnées de table. En fait, il croîtra très lentement au fil des ans. La seule façon de développer rapidement ibdata1 est si vous avez un ou plusieurs des éléments suivants:
CREATE TABLE
, DROP TABLE
, ALTER TABLE
)Chaque table InnoDB existera en dehors d'ibdata1
Supposons que vous ayez une table InnoDB nommée mydb.mytable. Si vous allez dans/var/lib/mysql/mydb, vous verrez deux fichiers représentant la table
ibdata1 ne contiendra plus de données et d'index InnoDB.
Avec l'option innodb_file_per_table dans /etc/my.cnf, vous pouvez exécuter OPTIMIZE TABLE mydb.mytable;
et le fichier /var/lib/mysql/mydb/mytable.ibd se réduira réellement.
Je l'ai fait plusieurs fois dans ma carrière en tant que DBA MySQL
En fait, la première fois que j'ai fait cela, j'ai réduit un fichier ibdata1 de 50 Go en 500 Mo.
Essaie. Si vous avez d'autres questions à ce sujet, écrivez-moi. Croyez-moi. Cela fonctionnera à court terme et à long terme !!!
Après avoir exécuté les étapes ci-dessus, comment déterminer quelles tables doivent être défragmentées? Il est possible de le découvrir, mais vous aurez le script.
Voici un exemple: Supposons que vous ayez la table mydb.mytable
. Avec innodb_file_per_table activé, vous avez le fichier /var/lib/mysql/mydb/mytable.ibd
Vous devrez récupérer deux numéros
FICHIERS À PARTIR DE L'OS: Vous pouvez vérifier la taille des fichiers à partir de l'OS comme ceci
ls -l /var/lib/mysql/mydb/mytable.ibd | awk '{print $5}'
FILESIZE FROM INFORMATION_SCHEMA: Vous pouvez vérifier la taille de fichier à partir de information_schema.tables comme ceci:
SELECT (data_length+index_length) tblsize FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='mytable';
Il suffit de soustraire la valeur INFORMATION_SCHEMA de la valeur du système d'exploitation et de diviser la différence par la valeur INFORMATION_SCHEMA.
De là, vous décidez quel pourcentage juge nécessaire de défragmenter ce tableau. Bien sûr, vous le défragmentez en utilisant l'une des commandes suivantes:
OPTIMIZE TABLE mydb.mytable;
ou
ALTER TABLE mydb.mytable ENGINE=InnoDB;
Si vous supprimez fréquemment des lignes (ou mettez à jour des lignes avec des types de données de longueur variable), vous pouvez vous retrouver avec beaucoup d'espace gaspillé dans vos fichiers de données, semblable à la fragmentation du système de fichiers.
Si vous n'utilisez pas le innodb_file_per_table
option, la seule chose que vous pouvez faire à ce sujet est d'exporter et d'importer la base de données, une procédure gourmande en temps et en disque.
Mais si vous utilisez innodb_file_per_table
, vous pouvez identifier et récupérer cet espace!
Avant la version 5.1.21, le compteur d'espace libre est disponible dans la colonne table_comment de information_schema.tables. Voici du SQL pour identifier les tables avec au moins 100M (en fait 97,65M) d'espace libre:
SELECT table_schema, table_name, table_comment FROM
information_schema.tables OERE LE MOTEUR COMME 'InnoDB' ET table_comment RLIKE 'InnoDB gratuit: ([0-9] {6,}). *';
À partir de la version 5.1.21, cela a été déplacé vers la colonne data_free (un endroit beaucoup plus approprié):
SELECT table_schema, table_name, data_free/1024/1024 AS data_free_MB FROM information_schema.tables OERE LE MOTEUR COMME 'InnoDB' ET data_free> 100 * 1024 * 1024;
Vous pouvez récupérer l'espace perdu en reconstruisant la table. La meilleure façon de procéder est d’utiliser ‘alter table’ sans rien changer:
ALTER TABLE `TableName` ENGINE=InnoDB;
C'est ce que MySQL fait en arrière-plan si vous exécutez ‘Optimiser table’ sur une table InnoDB. Il en résultera un verrou en lecture, mais pas un verrou de table complet. Le temps nécessaire dépend entièrement de la quantité de données dans le tableau (mais pas de la taille du fichier de données). Si vous avez une table avec un volume élevé de suppressions ou de mises à jour, vous souhaiterez peut-être l'exécuter tous les mois, voire chaque semaine.