मेरे परीक्षण मामले में अनुक्रमिक GUID कुंजियों की तुलना में अनुक्रमिक GUID कुंजियाँ तेज़ी से क्यों काम करती हैं?


39

अनुक्रमिक और गैर-अनुक्रमिक GUID की तुलना करने वाले इस प्रश्न को पूछने के बाद , मैंने 1 पर INSERT प्रदर्शन की तुलना करने की कोशिश की) एक GUID प्राथमिक कुंजी के साथ क्रमिक रूप से newsequentialid()तालिका, और 2) एक INT प्राथमिक कुंजी प्रारंभिक क्रमिक रूप से तालिका identity(1,1)। मैं पूर्णांकों की छोटी चौड़ाई के कारण उत्तरार्द्ध को सबसे तेज़ होने की उम्मीद करूंगा, और अनुक्रमिक GUID की तुलना में अनुक्रमिक पूर्णांक उत्पन्न करना भी सरल लगता है। लेकिन मेरे आश्चर्य के लिए, पूर्णांक कुंजी के साथ तालिका पर INSERTs क्रमिक GUID तालिका की तुलना में काफी धीमा थे।

यह परीक्षण चलाने के लिए औसत समय उपयोग (एमएस) दिखाता है:

NEWSEQUENTIALID()  1977
IDENTITY()         2223

क्या कोई इसे समझा सकता है?

निम्नलिखित प्रयोग किया गया था:

SET NOCOUNT ON

CREATE TABLE TestGuid2 (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))

CREATE TABLE TestInt (Id Int NOT NULL identity(1,1) PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))

DECLARE @BatchCounter INT = 1
DECLARE @Numrows INT = 100000


WHILE (@BatchCounter <= 20)
BEGIN 
BEGIN TRAN

DECLARE @LocalCounter INT = 0

    WHILE (@LocalCounter <= @NumRows)
    BEGIN
    INSERT TestGuid2 (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
    SET @LocalCounter +=1
    END

SET @LocalCounter = 0

    WHILE (@LocalCounter <= @NumRows)
    BEGIN
    INSERT TestInt (SomeDate,batchNumber) VALUES (GETDATE(),@BatchCounter)
    SET @LocalCounter +=1
    END

SET @BatchCounter +=1
COMMIT 
END

DBCC showcontig ('TestGuid2')  WITH tableresults
DBCC showcontig ('TestInt')  WITH tableresults

SELECT batchNumber,DATEDIFF(ms,MIN(SomeDate),MAX(SomeDate)) AS [NEWSEQUENTIALID()]
FROM TestGuid2
GROUP BY batchNumber

SELECT batchNumber,DATEDIFF(ms,MIN(SomeDate),MAX(SomeDate)) AS [IDENTITY()]
FROM TestInt
GROUP BY batchNumber

DROP TABLE TestGuid2
DROP TABLE TestInt

अद्यतन: स्क्रिप्ट को संशोधित करने के लिए, TEMP तालिका के आधार पर सम्मिलन करने के लिए, जैसे फिल सैंडलर, मिच गेहूं और मार्टिन द्वारा उदाहरण में, मुझे यह भी पता चलता है कि IDENTITY जितनी तेज होनी चाहिए। लेकिन यह पंक्तियों को सम्मिलित करने का पारंपरिक तरीका नहीं है, और मुझे अभी भी समझ में नहीं आया है कि पहले प्रयोग गलत क्यों हुआ: भले ही मैं अपने मूल उदाहरण से GETDATE () को छोड़ देता हूं, IDENTITY () अभी भी धीमा है। तो ऐसा लगता है कि IDENTITY () आउटपरफॉर्म NEWSEQUENTIALID () बनाने का एकमात्र तरीका अस्थायी तालिका में सम्मिलित करने के लिए पंक्तियों को तैयार करना है और इस अस्थायी तालिका का उपयोग करके बैच-सम्मिलित के रूप में कई सम्मिलन करना है। सब सब में, मुझे नहीं लगता कि हमने घटना के बारे में स्पष्टीकरण पाया है, और पहचान () अभी भी सबसे व्यावहारिक चरणों के लिए धीमी लगती है। क्या कोई इसे समझा सकता है?


4
केवल एक विचार: क्या यह हो सकता है कि एक नया GUID उत्पन्न करना बिना तालिका को शामिल किए बिना किया जा सकता है, जबकि अगले उपलब्ध पहचान मूल्य को प्राप्त करने के लिए अस्थायी रूप से दो थ्रेड्स / कनेक्शन सुनिश्चित करने के लिए किसी प्रकार का लॉक समान मूल्य प्राप्त नहीं करेगा? मैं वास्तव में अनुमान लगा रहा हूं। दिलचस्प सवाल!
क्रोधित व्यक्ति

4
कौन कहता है कि वे करते हैं ?? वहाँ बहुत सारे साक्ष्य नहीं हैं - किम्बर्ली ट्रिप के डिस्क स्थान को सस्ता देखें - यह बात नहीं है! ब्लॉग पोस्ट - वह काफी व्यापक समीक्षा करती है, और GUIDs हमेशा स्पष्ट रूप से बाहर निकलती हैंINT IDENTITY
marc_s

2
ठीक है, ऊपर प्रयोग इसके विपरीत दिखाता है, और परिणाम दोहराए जाते हैं।
someName

2
उपयोग करने के लिए IDENTITYटेबल लॉक की आवश्यकता नहीं होती है। वैचारिक रूप से मैं देख सकता था कि आप इसे MAX (id) + 1 लेने की उम्मीद कर सकते हैं, लेकिन वास्तव में अगला मूल्य संग्रहीत है। यह वास्तव में अगला GUID खोजने से अधिक तेज़ होना चाहिए।

4
इसके अलावा, संभवत: TestGuid2 तालिका के लिए भराव स्तंभ CHAR (88) होना चाहिए ताकि पंक्तियों को समान आकार दिया जा सके
मिच गेहूं

जवाबों:


19

मैंने GETDATE () को शामिल करने के प्रभाव को दूर करने के लिए @Phil Sandler के कोड को संशोधित किया (इसमें शामिल हो सकते हैं हार्डवेयर प्रभाव / व्यवधान ??), और पंक्तियों को समान लंबाई में बनाया।

[एसक्यूएल सर्वर २००० के बाद से समय संबंधी मुद्दों और उच्च-रिज़ॉल्यूशन टाइमर से संबंधित कई लेख आए हैं, इसलिए मैं उस प्रभाव को कम करना चाहता था।]

डेटा और लॉग फ़ाइल के साथ सरल पुनर्प्राप्ति मॉडल में दोनों को जिस तरह की आवश्यकता होती है, उसके आकार का तरीका यहां दिया गया है (सेकंड में): (नीचे सटीक कोड के आधार पर नए परिणाम के साथ अपडेट किया गया)

       Identity(s)  Guid(s)
       ---------    -----
       2.876        4.060    
       2.570        4.116    
       2.513        3.786   
       2.517        4.173    
       2.410        3.610    
       2.566        3.726
       2.376        3.740
       2.333        3.833
       2.416        3.700
       2.413        3.603
       2.910        4.126
       2.403        3.973
       2.423        3.653
    -----------------------
Avg    2.650        3.857
StdDev 0.227        0.204

उपयोग किया गया कोड:

SET NOCOUNT ON

CREATE TABLE TestGuid2 (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(88))

CREATE TABLE TestInt (Id Int NOT NULL identity(1,1) PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))

DECLARE @Numrows INT = 1000000

CREATE TABLE #temp (Id int NOT NULL Identity(1,1) PRIMARY KEY, rowNum int, adate datetime)

DECLARE @LocalCounter INT = 0

--put rows into temp table
WHILE (@LocalCounter < @NumRows)
BEGIN
    INSERT INTO #temp(rowNum, adate) VALUES (@LocalCounter, GETDATE())
    SET @LocalCounter += 1
END

--Do inserts using GUIDs
DECLARE @GUIDTimeStart DateTime = GETDATE()
INSERT INTO TestGuid2 (SomeDate, batchNumber) 
SELECT adate, rowNum FROM #temp
DECLARE @GUIDTimeEnd  DateTime = GETDATE()

--Do inserts using IDENTITY
DECLARE @IdTimeStart DateTime = GETDATE()
INSERT INTO TestInt (SomeDate, batchNumber) 
SELECT adate, rowNum FROM #temp
DECLARE @IdTimeEnd DateTime = GETDATE()

SELECT DATEDIFF(ms, @IdTimeStart, @IdTimeEnd) AS IdTime, DATEDIFF(ms, @GUIDTimeStart, @GUIDTimeEnd) AS GuidTime

DROP TABLE TestGuid2
DROP TABLE TestInt
DROP TABLE #temp
GO

@ मार्टिन की जांच को पढ़ने के बाद, मैंने दोनों मामलों में सुझाए गए TOP (@num) के साथ फिर से भाग लिया, अर्थात

...
--Do inserts using GUIDs
DECLARE @num INT = 2147483647; 
DECLARE @GUIDTimeStart DATETIME = GETDATE(); 
INSERT INTO TestGuid2 (SomeDate, batchNumber) 
SELECT TOP(@num) adate, rowNum FROM #temp; 
DECLARE @GUIDTimeEnd DATETIME = GETDATE();

--Do inserts using IDENTITY
DECLARE @IdTimeStart DateTime = GETDATE()
INSERT INTO TestInt (SomeDate, batchNumber) 
SELECT TOP(@num) adate, rowNum FROM #temp;
DECLARE @IdTimeEnd DateTime = GETDATE()
...

और यहाँ समय परिणाम हैं:

       Identity(s)  Guid(s)
       ---------    -----
       2.436        2.656
       2.940        2.716
       2.506        2.633
       2.380        2.643
       2.476        2.656
       2.846        2.670
       2.940        2.913
       2.453        2.653
       2.446        2.616
       2.986        2.683
       2.406        2.640
       2.460        2.650
       2.416        2.720

    -----------------------
Avg    2.426        2.688
StdDev 0.010        0.032

मैं वास्तविक निष्पादन योजना प्राप्त करने में सक्षम नहीं था, क्योंकि क्वेरी कभी वापस नहीं आई! ऐसा लगता है कि एक बग की संभावना है। (Microsoft SQL Server 2008 R2 (RTM) चलाना - 10.50.1600.1 (X64))


7
अच्छे बेंचमार्किंग के महत्वपूर्ण तत्व को नीटली दिखाता है: सुनिश्चित करें कि आप एक समय में केवल एक ही चीज को माप रहे हैं।
आरोन

आपको यहाँ क्या योजना मिलती है? क्या इसमें SORTGUID के लिए कोई ऑपरेटर है?
मार्टिन स्मिथ

@ मॉर्टिन: हाय, मैंने योजनाओं की जांच नहीं की (एक बार में कुछ चीजें करना :))। मैं थोड़ा बाद में
देखूंगा

@ मिच - इस पर कोई प्रतिक्रिया? मुझे मुख्य रूप से संदेह है कि आप यहां जो माप कर रहे हैं वह बड़ी आवेषण के लिए छापे को छांटने में लगने वाला समय है, जबकि दिलचस्प यह ओपी के मूल प्रश्न का उत्तर नहीं देता है, जो इस बारे में स्पष्टीकरण देता है कि अनुक्रमिक गाइड एकल पर पहचान कॉलम से बेहतर प्रदर्शन क्यों करते हैं ओपी के परीक्षण में पंक्ति आवेषण।
मार्टिन स्मिथ

2
@ मिच - हालांकि जितना अधिक मैं इसके बारे में सोचता हूं उतना कम मुझे समझ में आता है कि क्यों कोई भी कभी NEWSEQUENTIALIDभी उपयोग करना चाहेगा । यह सूचकांक को गहरा बना देगा, ओपी के मामले में 20% अधिक डेटा पृष्ठों का उपयोग करेगा और केवल तब तक बढ़ने की गारंटी है जब तक मशीन को रिबूट नहीं किया जाता है, इसलिए इसमें बहुत अधिक नुकसान हैं identity। यह सिर्फ इस मामले में लगता है कि क्वेरी प्लान एक और अनावश्यक में जोड़ता है!
मार्टिन स्मिथ

19

डेटा रिकवरी के साथ साधारण रिकवरी मॉडल में 1GB पर एक ताज़ा डेटाबेस और 3GB (लैपटॉप मशीन, एक ही ड्राइव पर दोनों फ़ाइलें) पर लॉग फ़ाइल और 100 मिनट के लिए रिकवरी अंतराल सेट (परिणामों की तिरछी नजर से बचने के लिए) एकल पंक्ति के समान परिणाम inserts

मैंने तीन मामलों का परीक्षण किया: प्रत्येक मामले के लिए मैंने 100,000 पंक्तियों को व्यक्तिगत रूप से निम्नलिखित तालिकाओं में सम्मिलित करने के 20 बैच किए। इस उत्तर के पुनरीक्षण इतिहास में पूर्ण लिपियों को पाया जा सकता है

CREATE TABLE TestGuid
  (
     Id          UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID() PRIMARY KEY,
     SomeDate    DATETIME, batchNumber BIGINT, FILLER CHAR(100)
  )

CREATE TABLE TestId
  (
     Id          Int NOT NULL identity(1, 1) PRIMARY KEY,
     SomeDate    DATETIME, batchNumber BIGINT, FILLER CHAR(100)
  )

CREATE TABLE TestInt
  (
     Id          Int NOT NULL PRIMARY KEY,
     SomeDate    DATETIME, batchNumber BIGINT, FILLER  CHAR(100)
  )  

तीसरी तालिका के लिए परीक्षण ने एक वृद्धिशील Idमान के साथ पंक्तियाँ डालीं लेकिन यह एक लूप में एक चर के मूल्य को बढ़ाकर स्वयं की गणना की गई थी।

20 बैचों में लगने वाले समय का लाभ उठाते हुए निम्नलिखित परिणाम दिए।

NEWSEQUENTIALID() IDENTITY()  INT
----------------- ----------- -----------
1999              2633        1878

निष्कर्ष

तो यह निश्चित रूप से identityनिर्माण प्रक्रिया के ऊपरी हिस्से के लिए प्रतीत होता है जो परिणामों के लिए जिम्मेदार है। आत्म गणना के पूर्णांक के लिए तो परिणाम केवल IO लागत पर विचार करने के बाद देखने के लिए क्या अपेक्षित होगा के साथ लाइन में अधिक हैं।

जब मैं ऊपर वर्णित कोड को संग्रहीत प्रक्रियाओं में डाल देता हूं और समीक्षा sys.dm_exec_procedure_statsकरता है तो यह निम्नलिखित परिणाम देता है

proc_name      execution_count      total_worker_time    last_worker_time     min_worker_time      max_worker_time      total_elapsed_time   last_elapsed_time    min_elapsed_time     max_elapsed_time     total_physical_reads last_physical_reads  min_physical_reads   max_physical_reads   total_logical_writes last_logical_writes  min_logical_writes   max_logical_writes   total_logical_reads  last_logical_reads   min_logical_reads    max_logical_reads
-------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- -------------------- --------------------
IdentityInsert 20                   45060360             2231067              2094063              2645079              45119362             2234067              2094063              2660080              0                    0                    0                    0                    32505                1626                 1621                 1626                 6268917              315377               276833               315381
GuidInsert     20                   34829052             1742052              1696051              1833055              34900053             1744052              1698051              1838055              0                    0                    0                    0                    35408                1771                 1768                 1772                 6316837              316766               298386               316774

तो उन परिणामों total_worker_timeमें लगभग 30% अधिक है। यह प्रतिनिधित्व करता है

सीपीयू समय की कुल राशि, माइक्रोसेकंड में, जो संकलित प्रक्रिया के निष्पादन के बाद से खपत हो गई थी।

तो यह केवल ऐसा प्रतीत होता है कि IDENTITYमान उत्पन्न करने वाला कोड सीपीयू से अधिक गहन है, जो उत्पन्न करता है NEWSEQUENTIALID()(2 आंकड़ों के बीच का अंतर 10231308 है जो औसतन लगभग 5µ प्रति इंसर्ट का औसत है।) और इस तालिका परिभाषा के लिए यह निश्चित मूल्य लागत है। अतिरिक्त तार्किक पठन को आगे बढ़ाने के लिए पर्याप्त रूप से उच्च था और कुंजी की अधिक चौड़ाई के कारण लिखता था। (एनबी: इत्ज़िक बेन गण ने यहां भी इसी तरह का परीक्षण किया और प्रति इंसर्ट में 2ik का जुर्माना पाया)

तो IDENTITYसीपीयू से अधिक गहन क्यों है UuidCreateSequential?

मेरा मानना ​​है कि इस लेख में इसकी व्याख्या की गई हैidentityउत्पन्न हर दसवें मूल्य के लिए, SQL सर्वर को डिस्क पर सिस्टम तालिकाओं में परिवर्तन लिखना होगा

MultiRow आवेषण के बारे में क्या?

जब एक बयान में 100,000 पंक्तियों को सम्मिलित किया जाता है, तो मैंने पाया कि अंतर अभी भी गायब हो गया है, शायद इस GUIDमामले में थोड़ा लाभ हुआ है लेकिन कहीं भी कटे हुए परिणामों के पास नहीं है। मेरे परीक्षण में 20 बैचों का औसत था

NEWSEQUENTIALID() IDENTITY()
----------------- -----------
1016              1088

इसका कारण यह है कि फिल के कोड में पेनल्टी स्पष्ट नहीं है और मिच के परिणामों का पहला सेट है क्योंकि ऐसा हुआ है कि जिस कोड का उपयोग मैंने किया था वह मल्टी रो सम्मिलित करना था SELECT TOP (@NumRows)। यह आशावादी को सही ढंग से उन पंक्तियों की संख्या का अनुमान लगाने से रोकता है जिन्हें सम्मिलित किया जाएगा।

यह लाभ का प्रतीत होता है क्योंकि एक निश्चित टिपिंग बिंदु है जिस पर यह (माना जाता है कि अनुक्रमिक) के लिए एक अतिरिक्त प्रकार का ऑपरेशन जोड़ देगा GUID

GUID क्रमबद्ध

बीओएल में व्याख्यात्मक पाठ से इस तरह के ऑपरेशन की आवश्यकता नहीं है ।

एक GUID बनाता है जो Windows के शुरू होने के बाद से एक निर्दिष्ट कंप्यूटर पर इस फ़ंक्शन द्वारा उत्पन्न किसी भी GUID से अधिक है। विंडोज को पुनरारंभ करने के बाद, GUID फिर से कम रेंज से शुरू हो सकती है, लेकिन अभी भी विश्व स्तर पर अद्वितीय है।

तो यह मुझे एक बग या लापता अनुकूलन लग रहा था कि एसक्यूएल सर्वर यह नहीं पहचानता है कि गणना स्केलर का आउटपुट पहले से ही सॉर्ट किया जाएगा क्योंकि यह स्पष्ट रूप से identityकॉलम के लिए पहले से ही करता है । ( संपादित करें मैं इस सूचना और अनावश्यक तरह इस मुद्दे को अब डेनलि में तय हो गई है )


यह प्रभाव की लेकिन सिर्फ स्पष्टता के हित में नंबर डेनी उद्धृत, 20 कैश्ड पहचान मूल्यों, वह सही नहीं है एक पूरी बहुत है ऐसा नहीं है कि - यह 10 होना चाहिए
हारून बर्ट्रेंड

@AaronBertrand - धन्यवाद। आपके द्वारा जोड़ा गया वह लेख सबसे अधिक जानकारीपूर्ण है।
मार्टिन स्मिथ

8

काफी सरल: GUID के साथ, यह IDENTITY के लिए लाइन में अगला नंबर जनरेट करने के लिए सस्ता है (GUID के वर्तमान मूल्य को संग्रहीत नहीं करना पड़ता है, IDENTITY होना चाहिए)। यह NEWSEQUENTIALGUID के लिए भी सही है।

आप परीक्षण को अधिक निष्पक्ष बना सकते हैं और एक बड़े CACHE के साथ SEQUENCER का उपयोग कर सकते हैं - जो कि IDENTITY से सस्ता है।

लेकिन जैसा कि एमआर कहते हैं, GUID को कुछ प्रमुख फायदे हैं। तथ्य की बात के रूप में, वे पहचान स्तंभों की तुलना में अधिक मापनीय हैं (लेकिन केवल अगर वे अनुक्रमिक नहीं हैं)।

देखें: http://blog.kejser.org/2011/10/05/boosting-insert-speed-by-generating-scalable-keys/


मुझे लगता है कि आप चूक गए कि वे अनुक्रमिक छापों का उपयोग कर रहे हैं।
मार्टिन स्मिथ

मार्टिन: क्रमिक GUID के लिए भी तर्क सही है। पहचान को संग्रहीत किया जाना है (पुनः आरंभ करने के बाद अपने पुराने मूल्य पर लौटने के लिए), अनुक्रमिक GUID में यह सीमा नहीं है।
थॉमस केजर

2
हां, मेरी टिप्पणी के बाद एहसास हुआ कि आप मेमोरी में स्टोर करने के बजाय लगातार स्टोर करने के बारे में बात कर रहे थे। 2012 के IDENTITYरूप में अच्छी तरह से के लिए एक कैश का उपयोग करता है । इसलिए यहाँ शिकायतें
मार्टिन स्मिथ

4

मैं इस प्रकार के प्रश्न से रोमांचित हूं। आपको इसे शुक्रवार की रात को पोस्ट क्यों करना पड़ा? :)

मुझे लगता है कि भले ही आपका परीक्षण केवल INSERT प्रदर्शन को मापने का इरादा है, आपने (हो सकता है) कई कारकों को पेश किया है जो भ्रामक हो सकते हैं (लूपिंग, एक लंबे समय तक चलने वाला लेनदेन, आदि)

मैं पूरी तरह से आश्वस्त नहीं हूं कि मेरा संस्करण कुछ भी साबित करता है, लेकिन पहचान इसमें GUID से बेहतर प्रदर्शन करती है (एक घर पीसी पर 3.2 सेकंड बनाम 6.8 सेकंड):

SET NOCOUNT ON

CREATE TABLE TestGuid2 (Id UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID() PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))

CREATE TABLE TestInt (Id Int NOT NULL identity(1,1) PRIMARY KEY,
SomeDate DATETIME, batchNumber BIGINT, FILLER CHAR(100))

DECLARE @Numrows INT = 1000000

CREATE TABLE #temp (Id int NOT NULL Identity(1,1) PRIMARY KEY, rowNum int)

DECLARE @LocalCounter INT = 0

--put rows into temp table
WHILE (@LocalCounter < @NumRows)
BEGIN
    INSERT INTO #temp(rowNum) VALUES (@LocalCounter)
    SET @LocalCounter += 1
END

--Do inserts using GUIDs
DECLARE @GUIDTimeStart DateTime = GETDATE()
INSERT INTO TestGuid2 (SomeDate, batchNumber) 
SELECT GETDATE(), rowNum FROM #temp
DECLARE @GUIDTimeEnd  DateTime = GETDATE()

--Do inserts using IDENTITY
DECLARE @IdTimeStart DateTime = GETDATE()
INSERT INTO TestInt (SomeDate, batchNumber) 
SELECT GETDATE(), rowNum FROM #temp
DECLARE @IdTimeEnd DateTime = GETDATE()

SELECT DATEDIFF(ms, @IdTimeStart, @IdTimeEnd) AS IdTime
SELECT DATEDIFF(ms, @GUIDTimeStart, @GUIDTimeEnd) AS GuidTime

DROP TABLE TestGuid2
DROP TABLE TestInt
DROP TABLE #temp

अन्य कारक जिसका किसी ने उल्लेख नहीं किया है, वह डेटाबेस रिकवरी मॉडल है, और लॉग फ़ाइल वृद्धि ...
मिच गेहूं

@ डेटा और लॉग फ़ाइल के साथ सरल रिकवरी मॉडल में एक नए डेटाबेस पर क्लिक करें जो मुझे आवश्यक है वह ओपी के समान परिणाम प्राप्त करने की आवश्यकता है।
मार्टिन स्मिथ

मुझे सिर्फ पहचान के लिए 2.560 सेकंड का समय मिला है, और गाइड के लिए 3.666 सेकंड (डेटा और लॉग फ़ाइल के साथ सरल पुनर्प्राप्ति मॉडल में दोनों को जिस तरह की आवश्यकता होती है, उसके आकार का तरीका है)
मिच गेहूं

@ मिच - ओपी के कोड के साथ एक ही लेनदेन में या फिल के कोड पर?
मार्टिन स्मिथ

इस पोस्टर कोड पर, इसीलिए मैं यहां टिप्पणी कर रहा हूं। मैंने अपने द्वारा उपयोग किए गए कोड को भी पोस्ट किया है ...
मिच गेहूं

3

मैंने आपकी नमूना स्क्रिप्ट को कई बार बैच काउंट और आकार में कुछ मोड़ दिया है (और इसे प्रदान करने के लिए आपका बहुत बहुत धन्यवाद)।

पहले मैं कहूंगा कि आप केवल कुंजियों के प्रदर्शन - INSERTगति के एक बार पहलू को माप रहे हैं । जब तक आप विशेष रूप से केवल तालिकाओं में डेटा प्राप्त करने से संबंधित होते हैं, तो इस जानवर के लिए बहुत अधिक संभव है।

मेरे निष्कर्ष सामान्य रूप से आपके जैसे थे। हालांकि, मैं में है कि विचरण का उल्लेख होगा INSERTके बीच गति GUIDऔर IDENTITY(int) थोड़ा है बड़ा के साथ GUIDसाथ की तुलना में IDENTITY- हो सकता है +/- रन के बीच 10%। जो बैच IDENTITYहर बार 2 - 3% से कम इस्तेमाल करते थे।

यह भी ध्यान दें, मेरा परीक्षण बॉक्स आपके मुकाबले स्पष्ट रूप से कम शक्तिशाली है, इसलिए मुझे छोटी पंक्ति की गणना का उपयोग करना पड़ा।


जब पीके एक GUID होता है तो क्या यह संभव है कि इंजन संबंधित रिकॉर्ड के भौतिक स्थान को निर्धारित करने के लिए एक इंडेक्स नहीं बल्कि एक हैशिंग एल्गोरिथ्म का उपयोग करता है? हैशेड प्राथमिक कुंजी के साथ एक विरल तालिका में डाला जाता है, हमेशा इंडेक्स ओवरहेड की अनुपस्थिति के कारण प्राथमिक कुंजी पर एक सूचकांक के साथ एक तालिका में आवेषण की तुलना में तेज होता है। यह सिर्फ एक सवाल है - अगर जवाब नहीं है तो मुझे वोट न करें। बस प्राधिकरण को लिंक की आपूर्ति करें।

1

मैं इसी विषय के लिए स्टैक्वोवरफ़्लो पर एक और दोषी को वापस भेजने जा रहा हूं - https://stackoverflow.com/questions/170346/what-are-the-performance-improvement-of-fterential-guid-over-standard-guid

एक बात मुझे पता है कि अनुक्रमिक GUID होने से यह है कि बहुत कम पत्ती के आंदोलन के कारण सूचकांक का उपयोग बेहतर होता है, और इसलिए एचडी की तलाश कम हो जाती है। मुझे लगता है कि इस वजह से, आवेषण तेजी से होगा, भी, क्योंकि इसमें बड़ी संख्या में पृष्ठों पर कुंजियों को वितरित नहीं करना पड़ता है।

मेरा व्यक्तिगत अनुभव यह है कि जब आप एक बड़े उच्च यातायात DB को लागू कर रहे हैं, तो GUID का उपयोग करना बेहतर है, क्योंकि यह अन्य प्रणालियों के साथ एकीकरण के लिए इसे और अधिक मापनीय बनाता है। यह प्रतिकृति के लिए, विशेष रूप से, और int / bigint सीमा के लिए जाता है .... ऐसा नहीं है कि आप बड़े संकेतों से बाहर निकलेंगे, लेकिन अंततः आप करेंगे, और वापस चक्र करेंगे।


1
आप BIGINTs से बाहर नहीं निकलते, कभी नहीं ... यह देखें: sqlmag.com/blog/it-possible-run-out-bigint-values
थॉमस केजर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.