2009-08-31 12 views
10

J'ai une base de données MySQL avec une table MyISAM avec 4 millions de lignes. Je mets à jour cette table environ une fois par semaine avec environ 2000 nouvelles lignes. Après la mise à jour, je modifie alors la table comme ceci:MySQL ALTER TABLE sur une très grande table - est-il sécuritaire de l'exécuter?

ALTER TABLE x ORDER BY PK DESC 

je commander la table par le champ de clé primaire dans l'ordre décroissant. Cela ne m'a causé aucun problème sur ma machine de développement (Windows avec 3 Go de mémoire). Trois fois je l'ai essayé avec succès sur le serveur Linux de production (avec 512 Mo de RAM - et en obtenant la table triée résultante en environ 6 minutes chaque fois), la dernière fois que je l'ai essayé, j'ai dû arrêter la requête après 30 minutes base de données à partir d'une sauvegarde.

Un serveur de 512 Mo peut-il faire face à cette instruction alter sur une table aussi grande? J'ai lu qu'une table temporaire est créée pour exécuter la commande ALTER TABLE. Question: Est-ce que cette commande alter peut être exécutée en toute sécurité? Quel devrait être le moment prévu pour l'altération de la table?

+1

Je pense que "très grande table" est probablement une surestimation. 4M lignes n'est pas une très grande table. 1 milliard pourrait éventuellement être. – MarkR

Répondre

0

Je créerais probablement une vue à la place qui est ordonnée par la valeur de PK, de sorte que pour une chose que vous n'avez pas besoin de verrouiller cette table énorme pendant que l'ALTER est en cours d'exécution.

+0

Merci pour la réponse ... La chose est que je ne me dérange pas de verrouiller la table pendant la mise à jour car il sera hors ligne de toute façon ... –

+0

Je ne crois pas qu'une vue aidera ici. MySQL a [deux stratégies] [1] pour les résolutions d'affichage: 'MERGE' et' TEMPTABLE'. Lors de l'utilisation de la fusion, vous ne bénéficierez d'aucun avantage car sa définition est simplement fusionnée avec l'instruction SELECT sélectionnée. 'TEMPTABLE', comme son nom l'indique, créera une table temporaire. Mais à quoi cela ressemble, créer la table temporaire est la cause du problème original. Donc, vous ne gagneriez rien d'autre que de rendre la maintenance plus difficile. [1]: http://dev.mysql.com/doc/refman/5.0/fr/view-algorithms.html – exhuma

3

Comme je viens de le lire, la requête ALTER TABLE ... ORDER BY ... est utile pour améliorer les performances dans certains scénarios. Je suis surpris que l'indice PK n'aide pas à cela. Mais, à partir de the MySQL docs, il semble que InnoDB utilise l'index. Cependant InnoDB a tendance à être plus lent que MyISAM. Cela dit, avec InnoDB vous n'auriez pas besoin de re-commander la table mais vous perdriez la vitesse fulgurante de MyISAM. Cela peut encore valoir un coup de feu.

La façon dont vous expliquez les problèmes, il semble qu'il y a trop de données chargées dans la mémoire (peut-être y a-t-il même un échange?). Vous pouvez facilement vérifier cela en surveillant votre utilisation de la mémoire. C'est difficile à dire car je ne connais pas très bien MySQL. D'autre part, je pense que votre problème se situe à un endroit très différent: Vous utilisez une machine avec seulement 512 Megs de RAM comme serveur de base de données avec une table contenant plus de 4Mio lignes ... Et vous effectuez une opération très lourde de mémoire sur toute la table sur cette machine. Il semble que 512Megs ne suffira pas pour cela.

Un problème beaucoup plus fondamental que je vois ici: Vous faites du développement (et probablement aussi des tests) dans un environnement très différent de l'environnement de production. Le genre de problème que vous expliquez est à prévoir. Votre machine de développement a six fois plus de mémoire que votre machine de production. Je crois pouvoir dire que le processeur est beaucoup plus rapide. Dans ce cas, je vous suggère de créer une machine virtuelle imitant votre site de production. De cette façon, vous pouvez facilement tester votre projet sans perturber le site de production.

+0

Les améliorations récentes apportées à InnoDB l'ont rendu performant à égalité avec MyISAM dans la plupart des scénarios. –

+0

@Bill: Intéressant. Donc, avec cela, vous pourriez dire que InnoDB est vraiment le chemin à parcourir? Même performance, plus de fonctionnalités. Après avoir vu ton profil, je pense pouvoir te croire. Pourtant, avez-vous des preuves pour aller avec ça? – exhuma

0

Ce que vous lui demandez de faire est de reconstruire la table entière et tous ses index; ceci est une opération coûteuse en particulier si les données ne rentrent pas dans le RAM. Cela se terminera, mais il sera beaucoup plus lent si les données ne rentrent pas dans la RAM, en particulier si vous avez beaucoup d'index.

Je remets en question votre jugement en choisissant de faire fonctionner une machine avec une telle minuscule mémoire en production. Quoi qu'il en soit:

  • Est-ce vraiment nécessaire? Quelle requête spécifique essayez-vous d'accélérer, et avez-vous essayé sans?
  • Avez-vous envisagé de faire en sorte que votre machine de développement ressemble davantage à la production?Je veux dire, l'utilisation d'une boîte de dev avec PLUS de mémoire n'est jamais une bonne idée, et l'utilisation d'un OS différent n'est certainement pas non plus.

Il y a probablement aussi un réglage que vous pouvez faire pour essayer d'aider; cela dépend en grande partie de votre schéma (index en particulier). 4M lignes ne sont pas très nombreuses (pour une machine avec des quantités normales de RAM).

+0

Salut Mark ... merci pour votre réponse ... La limite de la mémoire est due à des considérations budgétaires ... Je pensais que si le site pris sur je voudrais mettre à jour les spécifications du serveur ... Cependant, la raison de faire ALTER est que les utilisateurs peuvent exécuter une procédure stockée qui interroge cette table et je veux retourner les résultats dans l'ordre de "dernier inséré en premier". Je peux réaliser cela en utilisant un ORDER BY dans la requête elle-même, mais malheureusement cela semble très cher et ralentit considérablement les requêtes ... Donc, quand je mets à jour la table, je préexiste habituellement par PK desc pour ignorer cette commande. –

+0

Vous devez créer un index approprié pour que la requête ORDER BY n'ait pas besoin de trier. Vous pouvez vérifier cela en utilisant EXPLAIN (seulement si la requête n'est pas dans un SP). ALTER TABLE ... ORDER BY n'est pas une solution, car il ne garantit pas que les données restent stockées. – MarkR

+0

Salut Mark. J'ai 8 index sur cette table. Si je devais ajouter le champ PK (que je veux ordonner par desc) à la partie la plus à droite de chacun de ces index, les index seront toujours utilisés pour satisfaire la clause WHERE et, même si le champ de commande ne sera pas le plus à gauche préfixe de l'index (comme je l'ajouterai à l'extrême droite de chaque index), il peut encore être utilisé pour l'ORDER BY? Merci. –

0

Si vous utilisez InnoDB, vous ne devriez pas avoir à exécuter explicitement le ORDER BY après l'insertion ou lors de l'interrogation. Selon le manuel, InnoDB déjà par défaut la commande clé primaire MySQL 5.0 pour les résultats de la requête:

http://dev.mysql.com/doc/refman/5.0/en/alter-table.html#id4052480

tables MyISAM retour des enregistrements dans l'ordre d'insertion par défaut, au lieu, qui peut fonctionner aussi bien si vous n'ajoutez jamais la table, plutôt que d'utiliser une requête UPDATE pour modifier des lignes sur place.

1

est la clef automatique auto_increment? si c'est le cas, alors faire ALTER TABLE ... ORDER BY n'améliorera rien puisque tout sera inséré dans l'ordre de toute façon.

(sauf si vous avez beaucoup de suppressions)

+0

Merci pour la réponse. Cependant, le problème est que je veux donner les résultats dans l'ordre inverse de l'ordre de clé primaire ... –

+1

alors vous devez optimiser vos procédures stockées, les requêtes et les paramètres du serveur, ne pas essayer des choses de magie noire comme ALTER TABLE, ce qui fonctionne seulement à cause d'une bizarrerie dans les tables myisam. Si les performances de vos procédures et requêtes stockées souffrent lorsque vous les triez, vous devez ouvrir une nouvelle question et publier l'instruction CREATE TABLE, la requête/procédure et la sortie EXPLAIN. alors nous pouvons vous aider à optimiser la requête ou la configuration de votre serveur. – longneck