inserimento di righe da un tavolo all'altro, che SQL è più efficiente (join esterno vs scansione sequenziale)

StackOverflow https://stackoverflow.com/questions/1843344

Domanda

Ho bisogno di copiare le righe dalla tabella B per tabella A. Il requisito è quello di inserire solo le righe che non sono già in A.

La mia domanda è, che è di due seguenti è più efficiente:

A)

   INSERT INTO A (x, y, z)
   SELECT x, y, z
   FROM B b
   WHERE b.id NOT IN (SELECT id FROM A);

B)

   INSERT INTO A (x, y, z)
   SELECT b.x, b.y, b.z
   FROM B b LEFT OUTER JOIN A a
     ON b.id = a.id
   WHERE a.id is NULL;

Io parto dal presupposto la risposta dipende dalle dimensioni delle tabelle. Ma volevo sapere se c'è qualcosa di lampante sull'utilizzo di un approccio rispetto all'altro.

Per ridurre l'imprecisione, diciamo Tabella B avrà meno di 50K righe e Tabella A sarà sempre uguale o maggiore di dimensioni alla Tabella B per un fattore di 1-5.

Se qualcuno ha altri modi più efficaci per fare questo, fai dire.

È stato utile?

Soluzione

Credo che l'opzione B è meglio, soprattutto se la tabella A è più grande di tabella B di un fattore> 1.

Se si dispone di indici su a.id e b.id poi unendo sarà più veloce, secondo me, rispetto all'utilizzo in cui per ogni riga ...

Altri suggerimenti

Per aggiungere un'altra opzione:

INSERT INTO A (x, y, z)
SELECT B.x, B.y, B.z
FROM B
WHERE NOT EXISTS(SELECT * FROM A WHERE A.id = B.id)

Di solito vado con il LEFT JOIN approccio. Ma, se si vuole conoscere veramente ciò che è più efficiente, eseguire alcuni test sul proprio ambiente. Vedere che cosa i piani di esecuzione per ciascun approccio sono (si potrebbe scoprire che in realtà molteplici approcci risultano nello stesso piano di esecuzione).

Non dovrebbe importa - un buon ottimizzatore tratterà questi in modo identico. In pratica, ho visto per i piani di esecuzione stravaganti esattamente in questo caso, ma io sono noti per utilizzare entrambi gli stili in modo intercambiabile, a seconda dell'umore, la leggibilità e la complessità della query.

In SQL Server, l'opzione A non è disponibile quando è necessario iscriversi in una tupla di più Thana una singola colonna senza utilizzare un qualche tipo di concatenazione di soluzione (che non consiglio), che ci porta al gatto-scuoiatura opzione C (che io uso anche, soprattutto con le giunture sono davvero squirrely), che si estende a tuple direttamente:

INSERT INTO A (x, y, z) 
SELECT x, y, z 
FROM B b 
WHERE NOT EXISTS (SELECT * FROM A WHERE id = b.id); 

INSERT INTO A (x, y, z) 
SELECT x, y, z 
FROM B b 
WHERE NOT EXISTS (SELECT * FROM A WHERE id1 = b.id1 AND id2 = b.id2); 

A seconda del numero di righe e l'attività sul database, sarebbe di grande aiuto per eliminare tutti gli indici della tabella prima l'inserto e ricrearli in seguito.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top