2017-10-11 3 views
0

J'ai lancé une requête pour ajouter une colonne à une table en faisant correspondre l'ID d'une autre table. Les deux ont environ 600 millions de lignes donc c'est raisonnable que cela prenne un certain temps, mais ce qui m'inquiète, c'est qu'il y a des vitesses de lecture élevées (~ 500MB/s) sur le disque mais sqlite écrit 0B/s selon iotop. La taille de fichier sur mon fichier .db n'a pas changé en heures, mais l'ajout d'une colonne à une table de 600 millions de lignes doit changer AU MOINS un octet, non?La lecture haute mais absolument aucune écriture sur la requête SQLite normal?

Est-ce un comportement normal de SQLite? La machine est assez puissante, Ubuntu 16 sur i7 quad core avec 64 Go de RAM et NVMe SSD. Les requêtes et le schéma de la table sont ci-dessous.

ALTER TABLE tableA ADD address TEXT; 
UPDATE tableA SET address = (SELECT address FROM tableB WHERE tableA.ID = tx_out.ID); 

Table schema: 
CREATE TABLE tableA (
    ID TEXT, 
    column1 INT, 
    column2 TEXT, 
); 

CREATE TABLE tx_out (
    ID TEXT, 
    sequence INT, 
    address TEXT 
); 
+1

écrit peut-être dans le journal des transactions en premier? [WAL] (https://sqlite.org/wal.html) – lad2025

+0

@ lad2025 pourrait être, j'ai trouvé un fichier -journal par ce document https://sqlite.org/tempfiles.html mais c'est seulement 25KB, est-ce normal pour une transaction aussi importante? – jamzsabb

Répondre

2

L'ajout d'une colonne ne modifie pratiquement rien sur le disque; une ligne avec moins de valeurs que la table a des colonnes est supposée avoir des valeurs NULL dans les colonnes manquantes.

La mise à jour est extrêmement lent, car la sous-requête doit parcourir toute la table tx_outpour chaque ligne dans tableA. Vous pouvez l'accélérer considérablement avec un index sur la colonne tx_out.ID.

Lorsque la base de données doit réécrire toutes les lignes de toute façon, et vous avez l'espace disque, il est peut-être une meilleure idée de créer une nouvelle table:

INSERT INTO NewTable(ID, col1, col2, address) 
SELECT ID, col1, col2, address 
FROM tableA 
JOIN tableB USING (ID);  -- also needs an index to be fast 
+0

Cela a du sens, je n'ai pas l'espace disque pour faire une copie de la table, mais un index semble être une bonne idée. Dans le cas où quelqu'un de Google finit ici, ce guide http://www.sqlitetutorial.net/sqlite-index/ m'a vraiment aidé à comprendre le WTF des index et comment les utiliser. Merci pour la suggestion @CL – jamzsabb

+1

@jamzsabb - rappelez-vous que les index prennent aussi de l'espace disque. – Twelfth

1

Trop grand pour un commentaire

J'ai eu cette course pendant des jours sans changement ... Je pense qu'il est enclin à se verrouiller d'une manière ou une autre, je le tuais après sa 3e jour de ce qui semblait être aucun changement. J'ai rencontré des problèmes très similaires en essayant d'ajouter un nouvel index, mais celui-ci a été complété avec succès en 2 jours avant que je frappe mon seuil de 3 jours;) 3 jours possibles ne suffisaient-ils pas?

Ma préférence est maintenant de créer une deuxième table qui a la nouvelle colonne, charger la table avec les données de l'ancienne plus la nouvelle colonne, renommer l'ancienne table en X_oldtablename, renommer la nouvelle table en nom de table. Exécutez des tests et supprimez x_oldtablename après avoir vérifié que la nouvelle table fonctionne.

+0

Oui, je suis vraiment préoccupé maintenant, ne disposez pas de l'espace disque dur pour faire une copie, mais un autre utilisateur a recommandé un index, donc je le fais maintenant. Peut-être que cela aidera avec vos jointures aussi? Bonne chance man – jamzsabb