Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

SQL INSERT लेकिन डुप्लिकेट से बचें

संपादित करें :रोकने के लिए समवर्ती वातावरण में, WITH (UPDLOCK) . का उपयोग करें सहसंबद्ध उपश्रेणी में या EXCEPT 'डी SELECT . नीचे मैंने जो परीक्षण स्क्रिप्ट लिखी है, उसे इसकी आवश्यकता नहीं है, क्योंकि यह अस्थायी तालिकाओं का उपयोग करती है जो केवल वर्तमान कनेक्शन के लिए दृश्यमान हैं, लेकिन वास्तविक वातावरण में, उपयोगकर्ता तालिकाओं के विरुद्ध काम करना, यह आवश्यक होगा।

MERGE UPDLOCK की आवश्यकता नहीं है ।

एमसीएल के उत्तर पुन:से प्रेरित होकर:अद्वितीय अनुक्रमणिका और डेटाबेस को एक त्रुटि फेंकने दें, मैंने बेंचमार्क करने का निर्णय लिया सशर्त प्रविष्टियां बनाम try/catch .

परिणाम कोशिश/पकड़ पर सशर्त सम्मिलन का समर्थन करने लगते हैं, लेकिन वाईएमएमवी। यह एक बहुत ही सरल परिदृश्य है (एक कॉलम, छोटी टेबल, आदि), एक मशीन पर निष्पादित, आदि।

यहां परिणाम हैं (एसक्यूएल सर्वर 2008, बिल्ड 10.0.1600.2):

duplicates (short table)    
  try/catch:                14440 milliseconds / 100000 inserts
  conditional insert:        2983 milliseconds / 100000 inserts
  except:                    2966 milliseconds / 100000 inserts
  merge:                     2983 milliseconds / 100000 inserts

uniques
  try/catch:                 3920 milliseconds / 100000 inserts
  conditional insert:        3860 milliseconds / 100000 inserts
  except:                    3873 milliseconds / 100000 inserts
  merge:                     3890 milliseconds / 100000 inserts

  straight insert:           3173 milliseconds / 100000 inserts

duplicates (tall table)
  try/catch:                14436 milliseconds / 100000 inserts
  conditional insert:        3063 milliseconds / 100000 inserts
  except:                    3063 milliseconds / 100000 inserts
  merge:                     3030 milliseconds / 100000 inserts

ध्यान दें, अद्वितीय प्रविष्टियों पर भी, थोड़ा सा है सशर्त डालने की तुलना में कोशिश/पकड़ने के लिए अधिक ओवरहेड। मुझे आश्चर्य है कि क्या यह संस्करण, सीपीयू, कोर की संख्या, आदि से भिन्न होता है।

मैंने IF . को बेंचमार्क नहीं किया सशर्त प्रविष्टियां, बस WHERE . मुझे लगता है कि IF विविधता अधिक ओवरहेड दिखाएगी, क्योंकि ए) क्या आपके पास दो बयान होंगे, और बी) आपको लेनदेन में दो बयानों को लपेटने की आवश्यकता होगी और अलगाव स्तर को क्रमबद्ध करने योग्य (!) पर सेट करना होगा। अगर कोई चाहता इसका परीक्षण करने के लिए, आपको अस्थायी तालिका को एक नियमित उपयोगकर्ता तालिका में बदलना होगा (क्रमिक स्थानीय अस्थायी तालिकाओं पर लागू नहीं होता है)।

यहाँ स्क्रिप्ट है:

-- tested on SQL 2008.
-- to run on SQL 2005, comment out the statements using MERGE
set nocount on

if object_id('tempdb..#temp') is not null drop table #temp
create table #temp (col1 int primary key)
go

-------------------------------------------------------

-- duplicate insert test against a table w/ 1 record

-------------------------------------------------------

insert #temp values (1)
go

declare @x int, @y int, @now datetime, @duration int
select @x = 1, @y = 0, @now = getdate()
while @y < 100000 begin
  set @y = @y+1
  begin try 
    insert #temp select @x
  end try
  begin catch end catch
end
set @duration = datediff(ms,@now,getdate())
raiserror('duplicates (short table), try/catch: %i milliseconds / %i inserts',-1,-1,@duration,@y) with nowait
go

declare @x int, @y int, @now datetime, @duration int
select @x = 1, @y = 0, @now = getdate()
while @y < 100000 begin
  set @y = @y+1
  insert #temp select @x where not exists (select * from #temp where col1 = @x)
end
set @duration = datediff(ms,@now,getdate())
raiserror('duplicates (short table), conditional insert: %i milliseconds / %i inserts',-1,-1,@duration, @y) with nowait
go

declare @x int, @y int, @now datetime, @duration int
select @x = 1, @y = 0, @now = getdate()
while @y < 100000 begin
  set @y = @y+1
  insert #temp select @x except select col1 from #temp
end
set @duration = datediff(ms,@now,getdate())
raiserror('duplicates (short table), except: %i milliseconds / %i inserts',-1,-1,@duration, @y) with nowait
go

-- comment this batch out for SQL 2005
declare @x int, @y int, @now datetime, @duration int
select @x = 1, @y = 0, @now = getdate()
while @y < 100000 begin
  set @y = @y+1
  merge #temp t using (select @x) s (col1) on t.col1 = s.col1 when not matched by target then insert values (col1);
end
set @duration = datediff(ms,@now,getdate())
raiserror('duplicates (short table), merge: %i milliseconds / %i inserts',-1,-1,@duration, @y) with nowait
go

-------------------------------------------------------

-- unique insert test against an initially empty table

-------------------------------------------------------

truncate table #temp
declare @x int, @now datetime, @duration int
select @x = 0, @now = getdate()
while @x < 100000 begin
  set @x = @x+1
  insert #temp select @x
end
set @duration = datediff(ms,@now,getdate())
raiserror('uniques, straight insert: %i milliseconds / %i inserts',-1,-1,@duration, @x) with nowait
go

truncate table #temp
declare @x int, @now datetime, @duration int
select @x = 0, @now = getdate()
while @x < 100000 begin
  set @x = @x+1
  begin try 
    insert #temp select @x
  end try
  begin catch end catch
end
set @duration = datediff(ms,@now,getdate())
raiserror('uniques, try/catch: %i milliseconds / %i inserts',-1,-1,@duration, @x) with nowait
go

truncate table #temp
declare @x int, @now datetime, @duration int
select @x = 0, @now = getdate()
while @x < 100000 begin
  set @x = @x+1
  insert #temp select @x where not exists (select * from #temp where col1 = @x)
end
set @duration = datediff(ms,@now,getdate())
raiserror('uniques, conditional insert: %i milliseconds / %i inserts',-1,-1,@duration, @x) with nowait
go

truncate table #temp
declare @x int, @now datetime, @duration int
select @x = 0, @now = getdate()
while @x < 100000 begin
  set @x = @x+1
  insert #temp select @x except select col1 from #temp
end
set @duration = datediff(ms,@now,getdate())
raiserror('uniques, except: %i milliseconds / %i inserts',-1,-1,@duration, @x) with nowait
go

-- comment this batch out for SQL 2005
truncate table #temp
declare @x int, @now datetime, @duration int
select @x = 1, @now = getdate()
while @x < 100000 begin
  set @x = @x+1
  merge #temp t using (select @x) s (col1) on t.col1 = s.col1 when not matched by target then insert values (col1);
end
set @duration = datediff(ms,@now,getdate())
raiserror('uniques, merge: %i milliseconds / %i inserts',-1,-1,@duration, @x) with nowait
go

-------------------------------------------------------

-- duplicate insert test against a table w/ 100000 records

-------------------------------------------------------

declare @x int, @y int, @now datetime, @duration int
select @x = 1, @y = 0, @now = getdate()
while @y < 100000 begin
  set @y = @y+1
  begin try 
    insert #temp select @x
  end try
  begin catch end catch
end
set @duration = datediff(ms,@now,getdate())
raiserror('duplicates (tall table), try/catch: %i milliseconds / %i inserts',-1,-1,@duration,@y) with nowait
go

declare @x int, @y int, @now datetime, @duration int
select @x = 1, @y = 0, @now = getdate()
while @y < 100000 begin
  set @y = @y+1
  insert #temp select @x where not exists (select * from #temp where col1 = @x)
end
set @duration = datediff(ms,@now,getdate())
raiserror('duplicates (tall table), conditional insert: %i milliseconds / %i inserts',-1,-1,@duration, @y) with nowait
go

declare @x int, @y int, @now datetime, @duration int
select @x = 1, @y = 0, @now = getdate()
while @y < 100000 begin
  set @y = @y+1
  insert #temp select @x except select col1 from #temp
end
set @duration = datediff(ms,@now,getdate())
raiserror('duplicates (tall table), except: %i milliseconds / %i inserts',-1,-1,@duration, @y) with nowait
go

-- comment this batch out for SQL 2005
declare @x int, @y int, @now datetime, @duration int
select @x = 1, @y = 0, @now = getdate()
while @y < 100000 begin
  set @y = @y+1
  merge #temp t using (select @x) s (col1) on t.col1 = s.col1 when not matched by target then insert values (col1);
end
set @duration = datediff(ms,@now,getdate())
raiserror('duplicates (tall table), merge: %i milliseconds / %i inserts',-1,-1,@duration, @y) with nowait
go


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL सर्वर में एक विशिष्ट कॉलम वाली तालिकाएँ कैसे खोजें?

  2. मैं एक स्कीमा के मालिक एसक्यूएल सर्वर 2012 से एक उपयोगकर्ता को कैसे हटा सकता हूं?

  3. MS SQL सर्वर में भूले हुए लेनदेन का स्वचालित विलोपन

  4. sp_msforeachdb . के साथ त्रुटि होने पर डेटाबेस का नाम कैप्चर करने की आवश्यकता है

  5. SQL सर्वर पुनर्स्थापना त्रुटि - प्रवेश निषेध है