"INSERT di SELECT TOP(1) * FROM" vs. "INSERT TOP(1) di SELECT * FROM" + QUIZ

Ciao a tutti!

 
Oggi volevo parlare di INSERT DI SELECT in abbinamento all'operatore TOP.

Ma sorpresa... vi lascerò con un quesito al quale chi mi saprà rispondere avrà, come ambitissimo premio, "gli onori della cronaca" con la citazione nel mio prossimo articolo!!
Ho preparato un esempio che dovrebbe rendere abbastanza agevole rispondere al quesito!

Ma partiamo.

Supponiamo di dover inserire nella TABELLA_B alcuni record della TABELLA_A.
Utilizzando l'operatore TOP ci sono in realtà due modi diversi.

Possiamo scrivere la nostra stringa SQL così:

INSERT INTO TABELLA_B (...)
SELECT TOP(1) ....
FROM TABELLA_A

Oppure così:

INSERT TOP(1) INTO TABELLA_B (...)
SELECT ....
FROM TABELLA_A
 

Vediamo di creare un esempio ad hoc creandoci alcune tabelle tramite questi script:

create table elenco (idscarpe int, price float)

create table Scarpe (id int identity(1,1), ProductCode varchar(80))
Create clustered index idx_Clustered_Scarpe_id on Scarpe (id)
set identity_insert Scarpe on
insert into Scarpe(id,ProductCode) Select ... --- Mettiamoci dentro un po di dati
set identity_insert Scarpe off

create table Misure (id int identity(1,1), idScarpe int, Size varchar(80))
Create clustered index idx_Clustered_Misure_id on Misure (id)
set identity_insert Misure on
insert into Misure(id,idscarpe,Size) select --- Mettiamoci dentro un po di dati
set identity_insert Misure off

create table Prezzi (id int identity(1,1), idmisure int, Price float)
Create clustered index idx_Clustered_Prezzi_id on Prezzi (id)
set identity_insert Prezzi on
insert into Prezzi(id,idmisure,Price) select --- Mettiamoci dentro un po di dati
set identity_insert Prezzi off
 
La tabella elenco è la tabella dentro alla Quali inseriremo.
Le tabelle Scarpe, Misure e Prezzi sono le tabelle da cui faremo la SELECT.
La tabella Scarpe è ad esempio l'insieme delle nostre scarpe che abbiamo in casa.
La tabella Misure è una tabella di dettaglio della tabella scarpe e rappresenta la misura della scarpa.
La tabella Prezzi è una tabella di dettaglio della tabella Misure e rappresenza il prezzo della scarpa in funzione della misura.


Bene ora siamo pronti per eseguier il nostro test!

Scriviamo ad esempio questa stringa SQL:

Insert into elenco (idscarpe, price)
Select top(1) a.id, r.Price
from Scarpe a
join Misure l on a.id = l.idScarpe
join Prezzi r on r.idmisure = l.id
order by a.id


Ed osserviamo il suo piano di esecuzione:



Adesso scriviamo la stessa Query portando l'operatore TOP dentro l'insert!

Insert top(1) into elenco (idscarpe, price)
Select a.id, r.Price 
from Scarpe a
join Misure l on a.id = l.idScarpe
join Prezzi r on r.idmisure = l.id
order by a.id


Osserviamo adesso il piano di esecuzione della Query:



Cosa notate?

Ve lo dico io!

La seconda Query quella con il TOP nell'insert costa 1/100 della Prima Query.

Incredibile vero?

Se ci pensate le due Query producono lo stesso risultato ed il piano di esecuzione è simile..

Ecco allora il Quesito per chi ambisce al premio in palio:

Come mai la seconda Query è tanto più performante della prima?
E soppratutto da dove scaturisce la differenza?


Aspetto le vostre risposte..


Luca Biondi @ SQLServerPerformance blog!









Next post:Andare in debug su una Stored Procedure

Previous post: Query SARGABLE parte 2. Esempi



Comments

I Post più popolari

SQL Server, execution plan and the lazy spool (clearly explained)

SQL Server, datetime vs. datetime2

La clausola NOLOCK. Approfondiamo e facciamo chiarezza!