2017-05-08 1 views
1

Nous avons une table assez unoptimized avec la définition suivante:Mysql - temps estimé à baisser l'indice

CREATE TABLE `Usage` (
`TxnDate` varchar(30) DEFAULT NULL, 
`TxnID` decimal(13,2) NOT NULL, 
`UserID2015` varchar(20) DEFAULT NULL, 
`UserRMN` decimal(13,0) DEFAULT NULL, 
`CustomerNo` decimal(13,0) DEFAULT NULL, 
`OperatorName` varchar(50) DEFAULT NULL, 
`AggregatorName` varchar(30) DEFAULT NULL, 
`TransAmount` decimal(10,2) DEFAULT NULL, 
`MMPLTxnID` decimal(13,0) DEFAULT NULL, 
`ProductType` varchar(30) DEFAULT NULL, 
`YearMonthRMN` varchar(50) DEFAULT NULL, 
PRIMARY KEY (`TxnID`), 
UNIQUE KEY `TxnID` (`TxnID`) USING BTREE, 
KEY `TxnDate` (`TxnDate`), 
KEY `OperatorName` (`OperatorName`), 
KEY `AggregatorName` (`AggregatorName`), 
KEY `MMPLTxnID` (`MMPLTxnID`), 
KEY `ProductType` (`ProductType`), 
KEY `UserRMN` (`UserRMN`), 
KEY `YearMonthRMN` (`YearMonthRMN`) USING BTREE, 
KEY `CustomerNo` (`CustomerNo`) USING BTREE 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

Le tableau a abotu 170M records.

Je souhaite supprimer la clé primaire et ajouter à la place une clé primaire de numéro automatique. Jusqu'à présent, l'indice a chuté de 2h.

Pourquoi est-il si long de supprimer un index, y a-t-il un tri?

Comment puis-je estimer l'heure de suppression de l'index?

Lorsque j'ajouterai le numéro automatique, devrais-je estimer le temps de tri de la table ou cela ne sera-t-il pas nécessaire avec un nouvel index autonumber?

Répondre

3

Vous ne perdez pas simplement un index, vous supprimez la clé primaire.

Normalement, les tables InnoDB sont stockées en tant qu'index en cluster basé sur la clé primaire, donc en supprimant la clé primaire, elle doit créer une nouvelle table qui utilise la clé unique secondaire ou bien une clé générée automatiquement index clusterisé.

J'ai fait une bonne partie du conseil de MySQL, et la question de "combien de temps cela prendra-t-il?" est une question commune.

La création d'un nouvel index cluster sur votre serveur prend autant de temps que nécessaire. C'est difficile à prévoir. Cela dépend de plusieurs facteurs, tels que la rapidité des processeurs de votre serveur, la rapidité de votre stockage et l'intensité de la charge en concurrence pour la bande passante CPU et E/S. En d'autres termes, d'après mon expérience, il n'est pas possible de prédire combien de temps cela prendra.

Votre table sera reconstruite avec TxnID en tant que nouvel index clusterisé, qui est par coïncidence identique à la clé primaire. Mais apparemment MySQL Server ne reconnaît pas ce cas particulier comme un qui peut utiliser le raccourci de faire un inplace.

Votre table possède également huit autres index secondaires, dont cinq sont des varchars. Il doit construire ces index pendant la restructuration de la table. C'est beaucoup d'E/S pour construire ces index en plus de l'index clusterisé. C'est probablement ce qui prend tellement de temps.

Vous allez suivre un processus similaire lorsque vous ajouterez votre nouvelle clé primaire auto-incrémentée. Vous auriez pu gagner du temps si vous aviez supprimé votre ancienne clé primaire et créé la nouvelle clé primaire auto-incrémentée dans une instruction ALTER TABLE.

+0

Ceci est sur Amazon RDS, donc je pourrais au moins provisionner de la mémoire principale pour l'espace de journalisation des tailles d'index? – jdog

+0

La création d'index est généralement contrainte par les performances d'E/S au lieu de la mémoire. –

+0

Ok, mais à peu près je peux calculer: J'ai besoin de x Go pour trier les colonnes indexées en mémoire et j'ai besoin de x temps pour lire les colonnes, ce qui est contraint IO? Donc, je pourrais temporairement affecter le maximum d'E/S disponibles et assez de mémoire, de sorte que le tri ne se fasse pas avec l'échange sur le disque – jdog

2

(Je suis d'accord avec la réponse de Bill, voici plus de commentaires.)

Je tuerais le processus et repenser s'il y a un avantage dans un AUTO_INCREMENT. J'essaie de regarder au-delà de la question à la «vraie» question. Dans ce cas, il semble qu'il y ait quelque chose d'encore inexprimé qui appelle un AUTO_INCREMENT; S'il vous plaît élaborer.

Votre PRIMARY KEY actuel est 6 octets. Votre nouveau PK sera 4 octets si INT ou 8 octets si BIGINT. Ainsi, il n'y aura qu'une économie négligeable ou une perte d'utilisation de l'espace disque.

Toutes les recherches par TxnID seront ralenties à cause de l'IA. Et puisque TxnID est UNIQUE et non nul, il semble que le PK "naturel" optimal.

Un PK est une clé unique, donc UNIQUE(TxnID) est totalement redondant; DROPping cela économiserait de l'espace sans rien perdre. C'est la principale recommandation que je ferais (juste en regardant le schéma).

Lorsque je vois une table avec essentiellement chaque colonne étant NULL, je me méfie que le concepteur n'a pas pris une décision consciente au sujet de la nullité des colonnes.

DECIMAL(13,2) serait beaucoup de dollars ou d'euros, mais en tant que PK, il est assez inhabituel. Quoi de neuf?

latin1? Pas de plans pour la mondialisation?

Beaucoup d'index à colonne unique? WHERE a=1 AND b=2 supplie pour un composite INDEX(a,b).

Retour à temps estimer ...

Si la ALTER les reconstructions 8-9 index, puis est devrait faire ce qu'elle peut avec une sorte de disque. Cela implique d'écrire des choses sur le disque, en utilisant un tri efficace sur disque qui implique de la RAM, puis en lisant le résultat trié pour recréer l'index. Un tri est O (log N), le rendant ainsi non linéaire. Cela rend difficile la prédiction du temps pris. Certaines versions plus récentes de MariaDB tentative estimer le temps restant, mais je ne lui fais pas confiance.

Un index secondaire comprend la ou les colonnes en cours d'index, plus toute autre colonne de la PK. Chaque index dans cette table occupera environ 5-10 Go d'espace disque. Ce peut vous aider à convertir en IOP ou autre. Mais notez que (en supposant que vous n'avez pas beaucoup de RAM), que 5-10 Go sera relu quelques fois (plusieurs?) Fois pendant le tri qui reconstruit l'index. Lorsque vous faites plusieurs ALTERs, faites-les dans une seule instruction ALTER. De cette façon, tout le travail (en particulier la reconstruction des index secondaires) doit être fait qu'une seule fois.

Vous n'avez pas indiqué quelle version vous utilisez. Les anciennes versions donnent un choix: "COPIER": Créer une nouvelle table; copier des données sur; reconstruire des index; Renommer. Les nouvelles versions peuvent traiter secondaires index "INPLACE". Remarque: les modifications apportées au PRIMARY KEY nécessitent la méthode de copie.

+0

Merci pour les commentaires. Ceci est une base de données avec des transactions hors de l'Inde, d'où la taille de la décimale. Le processus d'importation de données est de qualité inférieure, par conséquent l'opérateur ne peut pas faire confiance à TxnId et a besoin du numéro automatique pour identifier les travaux d'importation. Je demande que cette base de données soit mise à la retraite, car nous en avons une plus récente, mieux conçue, mais nous n'en sommes pas encore là. En plus de cela, j'apprécie les calculs fournis, car cela aidera à optimiser la nouvelle base de données. MySQL est 5.7 – jdog

+0

Même avec plus d'informations, tout calcul serait seulement approximatif - beaucoup de choses font croître/rétrécir les BTrees. Pourtant, je pense que 5-10 Go est à peu près juste. «latin1» signifie qu'aucune des nombreuses langues indiennes ne peut être stockée «correctement». utf8mb4 (ou utf8) devrait être utilisé pour la nouvelle configuration. –

0

Pour les personnes intéressées:

  • C'est exécuté sur Amazon Aurora avec 30GB de données stockées. Je n'ai trouvé aucune information sur la façon dont IOPS est fourni pour cela, mais je m'attendais au pire des cas à ce que 90IOPS soient disponibles de manière cohérente. Pour écrire 10 Go in et out prendrait environ 4 heures.

  • J'ai mis à niveau l'instance vers db.r3.8xlarge avant d'exécuter la table alter.

  • puis a couru

    alter table `Usage` drop primary key, add id bigint auto_increment primary key 
    

il a fallu 1 h 21m, ce qui est beaucoup mieux que prévu.