J'ai une base de données ayant un certain nombre de tables.
Je souhaite supprimer certains enregistrements des tables, car le nombre d'enregistrements dépasse 20 000 ou 50 000.
Toutes les tables sont InnoDB. Et file_per_table
c'est éteint .
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.
Réponses:
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
L'exécution
OPTIMIZE TABLE
sur une table InnoDB stockée dans ibdata1 signifie 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
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) Supprimez 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 dont la croissance d'ibdata1 est rapide 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 !!!
MISE À JOUR 2012-04-19 09:23 EDT
Après avoir exécuté les étapes ci-dessus, comment pouvez-vous 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.ibdVous devrez récupérer deux numéros
FICHIER À PARTIR DE L'OS: vous pouvez vérifier la taille du fichier à partir de l'OS
FILESIZE FROM INFORMATION_SCHEMA: Vous pouvez vérifier la taille de fichier à partir de information_schema.tables comme ceci:
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:
ou
la source
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 l'
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:
À partir de la version 5.1.21, cela a été déplacé vers la colonne data_free (un endroit beaucoup plus approprié):
Vous pouvez récupérer l'espace perdu en reconstruisant la table. La meilleure façon de le faire est d'utiliser 'alter table' sans rien changer:
C'est ce que fait MySQL en arrière-plan si vous exécutez «optimiser la 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.
la source