web-dev-qa-db-fra.com

Remplacer dans la syntaxe de la requête

Je veux pouvoir mettre à jour une table du même schéma en utilisant une instruction "replace into". En fin de compte, je dois pouvoir mettre à jour une grande table avec des valeurs qui peuvent avoir changé.

Voici la requête que j'utilise pour commencer:

REPLACE INTO table_name
(visual, inspection_status, inspector_name, gelpak_name, gelpak_location),
VALUES (3, 'Partially Inspected', 'Me', 'GP1234', 'A01');

Ce que je ne comprends pas, c'est comment le moteur de base de données sait ce qui est une ligne en double et ce qui ne l'est pas. Ces données sont extrêmement importantes et je ne peux pas risquer de les corrompre. Est-ce aussi simple que "si toutes les colonnes de la liste ont la même valeur, il s'agit d'une ligne en double"?

J'essaie simplement de trouver un moyen efficace de le faire afin de pouvoir mettre à jour plus de 45 000 lignes en moins d'une minute.

41
kformeck

Comme le documentation dit:

REPLACE fonctionne exactement comme INSERT, sauf que si une ancienne ligne de la table a la même valeur qu'une nouvelle ligne pour une clé PRIMARY KEY ou un index UNIQUE, l'ancienne ligne est supprimée avant que la nouvelle ligne ne soit insérée.

74
Filipe Silva

REPLACE fonctionne beaucoup comme un INSERT qui écrase simplement les enregistrements qui ont le même PRIMARY KEY ou UNIQUE index, cependant, méfiez-vous.

Shlomi Noach écrit à propos du problème lié à l'utilisation de REPLACE INTOici :

Mais les gens au cœur faible comme moi devraient être conscients de ce qui suit: c'est une solution très lourde. C’est peut-être ce que vous recherchiez en termes de facilité d’utilisation, mais le fait est que sur les clés dupliquées, les opérations DELETE et INSERT sont effectuées, ce qui appelle un examen plus approfondi.

Chaque fois qu'une ligne est supprimée, tous les index doivent être mis à jour, et plus important encore, la clé primaire. Quand une nouvelle ligne est insérée, la même chose se produit. Surtout sur les tables InnoDB (en raison de leur nature en cluster), cela représente beaucoup de frais généraux. La restructuration d'un indice est une opération coûteuse. Les noeuds d'index peuvent avoir besoin d'être fusionnés lors de la suppression. Les nœuds peuvent avoir besoin d'être fractionnés à cause de INSERT. Après de nombreuses exécutions REPLACE INTO, il est fort probable que votre index soit plus fragmenté qu'il ne l'aurait été si vous aviez utilisé SELECT/UPDATE ou INSERT INTO ... ON DUPLICATE KEY

De plus, il y a la notion "bien, si la rangée n'existe pas, nous la créons. Si elle est présente, elle est simplement mise à jour". C'est faux. La ligne n'est pas simplement mise à jour, elle est complètement supprimée. Le problème est que s’il existe une clé PRIMARY KEY sur cette table et que REPLACE INTO ne spécifie pas de valeur pour la clé PRIMARY (par exemple, il s’agit d’une colonne AUTO_INCREMENT), la nouvelle ligne reçoit une valeur différente. vous recherchiez en termes de comportement.

De nombreuses utilisations de REPLACE INTO n'ont aucune intention de modifier les valeurs de PRIMARY KEY (ou d'autres clés uniques). Dans ce cas, il vaut mieux laisser seul. Sur un système de production que j'ai vu, la modification de REPLACE IN en INSERT INTO ... ON DPLICATE KEY entraînait un débit dix fois supérieur (mesuré en requêtes par seconde) et une réduction drastique de IO opérations et en charge moyenne.

En résumé, REPLACE INTO peut convenir à votre implémentation, mais vous pouvez trouver plus approprié (et moins risqué) d’utiliser INSERT ... ON DUPLICATE KEY UPDATE à la place.

15
Andrew Dunn

ou quelque chose comme ça:

insert ignore tbl1 (select * from tbl2);

UPDATE
        `tbl1` AS `dest`,
        (SELECT * FROM tbl2) AS `src`
    SET
       dest.field=src.field,
       dest.field=if (length(src.field)>0,src.field,dest.field) /* or anything like that*/
    WHERE
        `dest`.id = `src`.id; 
0
emmanuel