Ajout d'index aux grandes tables mysql

13

J'ai une table

| base_schedule_line_items | CREATE TABLE base_schedule_line_items(
idint (10) unsigned NOT NULL AUTO_INCREMENT,
installmentint (10) unsigned NOT NULL,
on_datedate NOT NULL,
actual_datedate DEFAULT NULL,
payment_typeint (11) NOT NULL,
scheduled_principal_outstandingdecimal (65,0) NOT NULL,
scheduled_principal_duedecimal (65,0) NOT NULL,
scheduled_interest_outstandingdecimal (65,0) NOT NULL,
scheduled_interest_duedecimal (65,0) NOT NULL,
currencyint (11) NOT NULL,
updated_atdatetime NOT NULL DEFAULT '2013-01-06 14:29:16',
created_atdatetime NOT NULL DEFAULT ' 2013-01-06 14:29:16 ',
loan_base_schedule_idint (10) unsigned NOT NULL,
lending_idint (10) unsigned NOT NULL,
rescheduletinyint (1) DEFAULT' 0 ',
PRIMARY KEY ( id),
KEY index_base_schedule_line_items_loan_base_schedule ( loan_base_schedule_id), KEY index_bslt_spd( scheduled_principal_due),
CLÉ index_bslt_lending(lending_id),
KEY index_bslt_actualdate( actual_date),
KEY index_bslt_spsila ( loan_base_schedule_id, scheduled_principal_due, scheduled_interest_due, actual_date),
KEY index_bslt_ondate( on_date),
KEY index_bslt_oa( on_date, actual_date),
KEY index_bslt_ol( on_date, loan_base_schedule_id),
KEY index_bslt_oli( on_date, lending_id)
) MOTEUR = InnoDB AUTO_INCREMENT = 30410126 DEFAULT charset = UTF8 |

Maintenant que cette table contient 30 millions d'enregistrements, j'ai besoin d'ajouter deux index supplémentaires à cela et il faut des années pour l'ajouter.

modifier la table base_schedule_line_items add index index_bslt_sla (schedule_principal_due, actual_date, lending_id);
modifier la table base_schedule_line_items add index index_bslt_ssla (schedule_principal_due, schedule_interest_due, lending_id, actual_date);

J'ai utilisé la requête mentionnée ci-dessous pour connaître la taille de la table

SELECT table_name AS "Tables", round (((data_length + index_length) / 1024/1024), 2) "Size in MB" FROM information_schema.TABLES WHERE table_schema = "my_database_name";

Le résultat est sorti comme

base_schedule_line_items | 20111.00

Je l'ai utilisé juste pour calculer la longueur des données et la longueur d'index omise

SELECT table_name AS "Tables", round (((data_length) / 1024/1024), 2) "Size in MB" FROM information_schema.TABLES WHERE table_schema = "my_database_name";

et le résultat était

base_schedule_line_items | 9497,00

Les index

Index_bslt_actualdate KEY (actual_date),
KEY index_bslt_spsila (loan_base_schedule_id, scheduled_principal_due, scheduled_interest_due, actual_date),
index_bslt_ondate KEY (on_date),
index_bslt_oa KEY (on_date, actual_date),
KEY index_bslt_ol (on_date, loan_base_schedule_id),
KEY index_bslt_oli (on_date, lending_id)

ont été ajoutés par moi, mais je ne sais pas trop dans quel but d'autres indices ont été ajoutés. Il s'agit d'une application assez importante. Maintenant, je dois ajouter ces deux indices mentionnés ci-dessus car ils m'aident à extraire un rapport à l'aide d'une instruction select et je trouve qu'il est très difficile de les ajouter. Toute aide serait grandement appréciée

user2294477
la source

Réponses:

16

L'activité de modification des grandes tables se fait en plusieurs phases:

  1. Créez une nouvelle table avec les champs et les index obligatoires, par exemple dans la base de données de test (structure juste)
  2. Vider les données de la table existante et les charger dans la table nouvellement créée dans la base de données de test
  3. Annoncez maintenant votre temps d'arrêt :)
  4. Échangez les tables en renommant - RENAME table ur_db.table_name to test.temp, test.table_name to ur_db.table_name, test.temp to test.table_name;Il s'agit d'une opération atomique prenant une fraction de seconde.
  5. Chargez les enregistrements supplémentaires dans la table nouvellement créée (les enregistrements qui sont arrivés après le vidage puis le chargement). Cette étape peut être effectuée avant l'étape: 3 également une fois pour réduire vos temps d'arrêt.
  6. Et votre système est de retour

Quelques notes:

  1. Vous n'avez pas besoin d'accéder directement au schéma d'information comme celui-ci, essayez d'utiliser SHOW TABLE STATUS from db like 'table_name'
  2. La vitesse de l'alter table est plus ou moins liée à la vitesse d'E / S. La dernière fois que nous avons exécuté une table de modification directe (sans les étapes ci-dessus), nous avions une taille de table de 40 Go +, cela a pris environ 4 heures. Si vos données de 20 Go prennent des années, vous travaillez sur une machine obsolète.
  3. Supprimez également les index indésirables comme index_bslt_ondate, index_base_schedule_line_items_loan_base_schedulecertains autres index ont la colonne la plus à gauche comme colonne indexée

Veuillez me faire savoir si vous avez besoin d'éclaircissements sur l'une de ces étapes.

Edit: Un simple script python pour automatiser le processus https://github.com/georgecj11/hotswap_mysql_table.git

georgecj11
la source
10

Vous pouvez utiliser un outil comme pt-online-schema-change pour ajouter l'index sans bloquer votre application. La logique de base est la suivante:

  • créer une copie vide de la table avec le nouvel index
  • ajouter des déclencheurs à la table existante afin que toutes les modifications qui atteignent la table soient appliquées à la copie de la table *
  • commencer à copier les lignes de l'ancienne table vers la nouvelle
  • une fois la copie terminée, échangez les tableaux
  • déposer l'ancienne table

* L'outil ne fonctionne pas s'il y a des déclencheurs existants sur la table

Le comportement de permutation et de suppression peut être ajusté en fonction des options transmises à l'outil.

En outre, il existe des problèmes avec les clés étrangères, alors assurez-vous de lire la documentation de l'outil pour bien comprendre ce qu'il fait.

Et bien sûr, il est sage de s'assurer que vous disposez d'une sauvegarde de la table pour pouvoir la restaurer si nécessaire.

Derek Downey
la source