चूँकि आप अनुक्रम का उपयोग कर रहे हैं, आप उसी NEXT VALUE फ़ॉर फ़ंक्शन का उपयोग कर सकते हैं - जो आपके पास Id
प्राथमिक कुंजी फ़ील्ड पर पहले से ही डिफ़ॉल्ट बाधा है - Id
समय से पहले एक नया मान उत्पन्न करने के लिए । पहले मूल्य उत्पन्न करने का मतलब है कि आपको नहीं होने के बारे में चिंता करने की आवश्यकता नहीं है SCOPE_IDENTITY
, जिसका अर्थ है कि आपको नए मान प्राप्त करने के लिए OUTPUT
या तो खंड या अतिरिक्त SELECT
करने की आवश्यकता नहीं है ; आपके द्वारा करने से पहले आपके पास मूल्य होगा INSERT
, और आपको SET IDENTITY INSERT ON / OFF
:-) के साथ गड़बड़ करने की आवश्यकता नहीं है
ताकि समग्र स्थिति के हिस्से का ध्यान रखा जाए। दूसरा भाग दो प्रक्रियाओं के समवर्ती मुद्दे को संभाल रहा है, ठीक उसी समय, ठीक उसी स्ट्रिंग के लिए एक मौजूदा पंक्ति नहीं ढूंढ रहा है, और इसके साथ आगे बढ़ रहा है INSERT
। चिंता अद्वितीय बाधा उल्लंघन से बचने के बारे में है जो घटित होगी।
इस प्रकार के समसामयिक मुद्दों को संभालने का एक तरीका यह है कि इस विशेष ऑपरेशन को सिंगल थ्रेडेड करने के लिए बाध्य किया जाए। ऐसा करने का तरीका एप्लिकेशन लॉक का उपयोग करके है (जो सत्रों में काम करता है)। प्रभावी होने के दौरान, वे इस तरह की स्थिति के लिए थोड़े भारी हो सकते हैं जहां टकराव की आवृत्ति संभवतः काफी कम है।
टकरावों से निपटने का दूसरा तरीका यह है कि वे स्वीकार करें कि वे कभी-कभी होते हैं और उनसे बचने की कोशिश करने के बजाय उन्हें संभालते हैं। TRY...CATCH
निर्माण का उपयोग करते हुए , आप प्रभावी रूप से एक विशिष्ट त्रुटि (इस मामले में: "अद्वितीय बाधा उल्लंघन", Msg 2601) में फंस सकते SELECT
हैं और Id
मूल्य प्राप्त करने के लिए फिर से निष्पादित कर सकते हैं क्योंकि हम जानते हैं कि यह अब CATCH
उस विशेष के साथ ब्लॉक में होने के कारण मौजूद है त्रुटि। अन्य त्रुटियों को विशिष्ट RAISERROR
/ RETURN
या THROW
तरीके से नियंत्रित किया जा सकता है।
टेस्ट सेटअप: अनुक्रम, तालिका और अद्वितीय सूचकांक
USE [tempdb];
CREATE SEQUENCE dbo.MagicNumber
AS INT
START WITH 1
INCREMENT BY 1;
CREATE TABLE dbo.NameLookup
(
[Id] INT NOT NULL
CONSTRAINT [PK_NameLookup] PRIMARY KEY CLUSTERED
CONSTRAINT [DF_NameLookup_Id] DEFAULT (NEXT VALUE FOR dbo.MagicNumber),
[ItemName] NVARCHAR(50) NOT NULL
);
CREATE UNIQUE NONCLUSTERED INDEX [UIX_NameLookup_ItemName]
ON dbo.NameLookup ([ItemName]);
GO
टेस्ट सेटअप: संग्रहीत प्रक्रिया
CREATE PROCEDURE dbo.GetOrInsertName
(
@SomeName NVARCHAR(50),
@ID INT OUTPUT,
@TestRaceCondition BIT = 0
)
AS
SET NOCOUNT ON;
BEGIN TRY
SELECT @ID = nl.[Id]
FROM dbo.NameLookup nl
WHERE nl.[ItemName] = @SomeName
AND @TestRaceCondition = 0;
IF (@ID IS NULL)
BEGIN
SET @ID = NEXT VALUE FOR dbo.MagicNumber;
INSERT INTO dbo.NameLookup ([Id], [ItemName])
VALUES (@ID, @SomeName);
END;
END TRY
BEGIN CATCH
IF (ERROR_NUMBER() = 2601) -- "Cannot insert duplicate key row in object"
BEGIN
SELECT @ID = nl.[Id]
FROM dbo.NameLookup nl
WHERE nl.[ItemName] = @SomeName;
END;
ELSE
BEGIN
;THROW; -- SQL Server 2012 or newer
/*
DECLARE @ErrorNumber INT = ERROR_NUMBER(),
@ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE();
RAISERROR(N'Msg %d: %s', 16, 1, @ErrorNumber, @ErrorMessage);
RETURN;
*/
END;
END CATCH;
GO
कसौटी
DECLARE @ItemID INT;
EXEC dbo.GetOrInsertName
@SomeName = N'test1',
@ID = @ItemID OUTPUT;
SELECT @ItemID AS [ItemID];
GO
DECLARE @ItemID INT;
EXEC dbo.GetOrInsertName
@SomeName = N'test1',
@ID = @ItemID OUTPUT,
@TestRaceCondition = 1;
SELECT @ItemID AS [ItemID];
GO
ओपी से सवाल
इससे बेहतर क्यों है MERGE
? क्या मुझे क्लॉज TRY
का उपयोग करके समान कार्यक्षमता नहीं मिलेगी WHERE NOT EXISTS
?
MERGE
विभिन्न "मुद्दे" हैं (कई संदर्भ @ SqlZim के उत्तर से जुड़े हुए हैं, इसलिए उस जानकारी को डुप्लिकेट करने की कोई आवश्यकता नहीं है)। और, इस दृष्टिकोण (कम विवाद) में कोई अतिरिक्त लॉकिंग नहीं है, इसलिए इसे संगामिति पर बेहतर होना चाहिए। इस दृष्टिकोण में, आपको कभी भी एक अद्वितीय बाधा का उल्लंघन नहीं मिलेगा, सभी बिना किसी HOLDLOCK
आदि के, यह काम करने की बहुत अधिक गारंटी है।
इस दृष्टिकोण के पीछे तर्क है:
- यदि आपके पास इस प्रक्रिया का पर्याप्त निष्पादन है जैसे कि आपको टकरावों के बारे में चिंता करने की आवश्यकता है, तो आप यह नहीं करना चाहते हैं:
- आवश्यकता से अधिक कदम उठाना
- आवश्यकता से अधिक समय तक किसी भी संसाधन पर ताले रखें
- चूंकि टकराव केवल नई प्रविष्टियों पर हो सकता है ( बिल्कुल उसी समय प्रस्तुत की गई नई प्रविष्टियाँ ),
CATCH
पहली जगह में ब्लॉक में गिरने की आवृत्ति बहुत कम होगी। यह उस कोड को ऑप्टिमाइज़ करने के लिए अधिक समझ में आता है जो उस कोड के बजाय 99% चलाएगा जो 1% समय तक चलेगा (जब तक कि दोनों को अनुकूलित करने की कोई लागत नहीं है, लेकिन यहां ऐसा नहीं है)।
@ SqlZim के उत्तर से टिप्पणी (जोर दिया गया)
मैं व्यक्तिगत रूप से कोशिश करना चाहता हूं और जब संभव हो तो ऐसा करने से बचने के लिए एक समाधान दर्जी करें । इस मामले में, मुझे नहीं लगता कि ताले का उपयोग करना serializable
एक भारी हाथ है, और मुझे विश्वास है कि यह अच्छी तरह से उच्च संगामिति को संभाल लेगा।
मैं इस पहले वाक्य से सहमत होता अगर यह राज्य में संशोधित होता "और _ विवेकपूर्ण"। सिर्फ इसलिए कि तकनीकी रूप से कुछ संभव नहीं है, इसका मतलब यह नहीं है कि स्थिति (यानी इच्छित उपयोग-मामला) इससे लाभान्वित होगी।
इस दृष्टिकोण के साथ मैं जो मुद्दा देख रहा हूं वह यह है कि यह सुझाव दिए जाने की तुलना में अधिक लॉक है। "क्रमबद्ध" पर उद्धृत दस्तावेज को फिर से पढ़ना महत्वपूर्ण है, विशेष रूप से निम्नलिखित (जोर दिया गया):
- अन्य लेनदेन मुख्य मूल्यों के साथ नई पंक्तियाँ नहीं डाल सकते हैं जो वर्तमान लेनदेन में किसी भी बयान द्वारा पढ़ी गई कुंजियों की श्रेणी में आते हैं जब तक कि वर्तमान लेनदेन पूरा नहीं हो जाता।
अब, यहाँ उदाहरण कोड में टिप्पणी है:
SELECT [Id]
FROM dbo.NameLookup WITH (SERIALIZABLE) /* hold that key range for @vName */
ऑपरेटिव शब्द "रेंज" है। लिया जा रहा ताला केवल मूल्य पर नहीं है @vName
, लेकिन अधिक सटीक रूप से शुरू होने वाली सीमा हैवह स्थान जहाँ यह नया मान जाना चाहिए (अर्थात जहाँ नया मान फ़िट होता है, उसके दोनों ओर मौजूदा प्रमुख मानों के बीच), लेकिन स्वयं मान नहीं। वर्तमान में वर्तमान में देखे जा रहे मूल्य के आधार पर नए मूल्यों को सम्मिलित करने से अन्य प्रक्रियाओं को अवरुद्ध किया जाएगा। यदि लुकअप रेंज के शीर्ष पर किया जा रहा है, तो ऐसी किसी भी चीज़ को सम्मिलित करना जो उस स्थान को अवरुद्ध कर सकती है। उदाहरण के लिए, यदि मान "a", "b", और "d" मौजूद हैं, तो यदि एक प्रक्रिया "f" पर SELECT कर रही है, तो मान "g" या "e" प्रविष्ट करना संभव नहीं होगा ( चूँकि उनमें से कोई भी "d") के तुरंत बाद आएगा। लेकिन, "c" का मान सम्मिलित करना संभव होगा क्योंकि इसे "आरक्षित" श्रेणी में नहीं रखा जाएगा।
निम्नलिखित उदाहरण को इस व्यवहार को चित्रित करना चाहिए:
(क्वेरी टैब में (सत्र) # 1)
INSERT INTO dbo.NameLookup ([ItemName]) VALUES (N'test5');
BEGIN TRAN;
SELECT [Id]
FROM dbo.NameLookup WITH (SERIALIZABLE) /* hold that key range for @vName */
WHERE ItemName = N'test8';
--ROLLBACK;
(क्वेरी टैब में (सत्र) # 2)
EXEC dbo.NameLookup_getset_byName @vName = N'test4';
-- works just fine
EXEC dbo.NameLookup_getset_byName @vName = N'test9';
-- hangs until you either hit "cancel" in this query tab,
-- OR issue a COMMIT or ROLLBACK in query tab #1
EXEC dbo.NameLookup_getset_byName @vName = N'test7';
-- hangs until you either hit "cancel" in this query tab,
-- OR issue a COMMIT or ROLLBACK in query tab #1
EXEC dbo.NameLookup_getset_byName @vName = N's';
-- works just fine
EXEC dbo.NameLookup_getset_byName @vName = N'u';
-- hangs until you either hit "cancel" in this query tab,
-- OR issue a COMMIT or ROLLBACK in query tab #1
इसी तरह, यदि मूल्य "C" मौजूद है, और "A" का चयन किया जा रहा है, और (इसलिए लॉक किया गया है), तो आप "D" का मान डाल सकते हैं, लेकिन "B" का मान नहीं:
(क्वेरी टैब में (सत्र) # 1)
INSERT INTO dbo.NameLookup ([ItemName]) VALUES (N'testC');
BEGIN TRAN
SELECT [Id]
FROM dbo.NameLookup WITH (SERIALIZABLE) /* hold that key range for @vName */
WHERE ItemName = N'testA';
--ROLLBACK;
(क्वेरी टैब में (सत्र) # 2)
EXEC dbo.NameLookup_getset_byName @vName = N'testD';
-- works just fine
EXEC dbo.NameLookup_getset_byName @vName = N'testB';
-- hangs until you either hit "cancel" in this query tab,
-- OR issue a COMMIT or ROLLBACK in query tab #1
निष्पक्ष होने के लिए, मेरे सुझाए गए दृष्टिकोण में, जब कोई अपवाद होता है, तो लेन-देन लॉग में 4 प्रविष्टियां होंगी जो इस "क्रमबद्ध लेनदेन" दृष्टिकोण में नहीं होंगी। लेकिन, जैसा कि मैंने ऊपर कहा है, अगर अपवाद समय का 1% (या 5%) भी होता है, जो कि प्रारंभिक चयन को अस्थायी रूप से अवरुद्ध INSERT संचालन के कहीं अधिक संभावित मामले की तुलना में बहुत कम प्रभाव डालता है।
एक और, यद्यपि मामूली, इस "क्रमबद्ध लेनदेन + OUTPUT क्लॉज" दृष्टिकोण के साथ मुद्दा यह है कि OUTPUT
क्लॉज (इसके वर्तमान उपयोग में) परिणाम सेट के रूप में डेटा वापस भेजता है। एक परिणाम सेट के लिए एक साधारण OUTPUT
पैरामीटर की तुलना में अधिक ओवरहेड (संभवतः दोनों तरफ: SQL सर्वर में आंतरिक कर्सर को प्रबंधित करने के लिए, और ऐप लेयर में DataReader ऑब्जेक्ट को प्रबंधित करने के लिए) की आवश्यकता होती है । यह देखते हुए कि हम केवल एकल स्केलर मान के साथ काम कर रहे हैं, और यह अनुमान निष्पादन की एक उच्च आवृत्ति है, कि परिणाम सेट का अतिरिक्त ओवरहेड संभवतः जोड़ता है।
जबकि OUTPUT
क्लॉज का उपयोग इस तरह किया जा सकता है OUTPUT
कि पैरामीटर को वापस किया जा सकता है , जिसके लिए एक अस्थायी टेबल या टेबल वैरिएबल बनाने के लिए अतिरिक्त चरणों की आवश्यकता होगी, और फिर उस टेम्प टेबल / टेबल वैरिएबल के मान को OUTPUT
पैरामीटर में से चुनने के लिए ।
इसके अलावा स्पष्टीकरण: मेरे जवाब के लिए @ SqlZim की प्रतिक्रिया (अद्यतन उत्तर) @ SqlZim की प्रतिक्रिया (मूल उत्तर में) के लिए मेरे वक्तव्य में संगामिति और प्रदर्शन;;
क्षमा करें यदि यह हिस्सा एक लंबा-चौड़ा है, लेकिन इस बिंदु पर हम दो दृष्टिकोणों की बारीकियों के लिए नीचे हैं।
मेरा मानना है कि जिस तरह से जानकारी serializable
प्रस्तुत की गई है, वह मूल प्रश्न में प्रस्तुत परिदृश्य के रूप में उपयोग करते समय किसी से मुठभेड़ की उम्मीद कर सकती है ।
हां, मैं मानता हूं कि मैं पक्षपाती हूं, हालांकि निष्पक्ष होना चाहिए:
- मानव के लिए यह असंभव नहीं है कि वह कम से कम कुछ छोटी डिग्री का पक्षपाती हो, और मैं उसे कम से कम रखने की कोशिश करूं,
- जो उदाहरण दिया गया था वह सरल था, लेकिन यह व्यवहार को बिना जटिल किए उसे स्पष्ट करने के लिए था। अत्यधिक आवृत्ति का इरादा नहीं था, हालांकि मैं समझता हूं कि मैंने भी स्पष्ट रूप से राज्य नहीं किया था और इसे वास्तव में मौजूद की तुलना में बड़ी समस्या के रूप में पढ़ा जा सकता है। मैं नीचे स्पष्ट करने का प्रयास करूंगा।
- मैंने दो मौजूदा कुंजियों ("क्वेरी टैब 1 का दूसरा सेट" और "क्वेरी टैब 2" ब्लॉक) के बीच एक सीमा को लॉक करने का एक उदाहरण भी शामिल किया।
- मुझे अपने दृष्टिकोण की "छिपी हुई लागत" का पता चला (और स्वयंसेवक), कि
INSERT
एक अद्वितीय बाधा उल्लंघन के कारण हर बार चार अतिरिक्त ट्रैन लॉग प्रविष्टियाँ विफल हो जाती हैं। मैंने ऐसा किसी अन्य उत्तर / पोस्ट में नहीं देखा है।
@ Gbn के "JFDI" दृष्टिकोण के बारे में, माइकल जे। स्वार्ट की "अग्ली प्रैग्मटिज्म फॉर द विन" पोस्ट, और माइकल की पोस्ट पर आरोन बर्ट्रैंड की टिप्पणी (उनके परीक्षण से पता चलता है कि प्रदर्शन में क्या कमी आई है), और आपकी टिप्पणी "माइकल जे के अनुकूलन" पर। । स्टीवर्ट के @ gbn की कोशिश पकड़ो JFDI प्रक्रिया को "बताते हुए कहा:"
यदि आप मौजूदा मानों के चयन की तुलना में अधिक बार नए मान सम्मिलित कर रहे हैं, तो यह @ srutzky के संस्करण से अधिक प्रदर्शनकारी हो सकता है। अन्यथा मैं इस पर @ srutzky के संस्करण को पसंद करूंगा।
"JFDI" दृष्टिकोण से संबंधित उस gbn / माइकल / आरोन चर्चा के संबंध में, यह मेरे सुझाव को gbn के "JFDI" दृष्टिकोण के बराबर करना गलत होगा। "जाओ या सम्मिलित करें" ऑपरेशन की प्रकृति के कारण, मौजूदा रिकॉर्ड के लिए मूल्य SELECT
प्राप्त करने के लिए एक स्पष्ट आवश्यकता है ID
। यह चयन IF EXISTS
चेक के रूप में कार्य करता है , जो इस दृष्टिकोण को आरोन के परीक्षणों के "चेकट्रीकैच" भिन्नता के समान बनाता है। माइकल का फिर से लिखा कोड (और माइकल के अनुकूलन का आपका अंतिम रूपांतर) में एक WHERE NOT EXISTS
ऐसा ही चेक पहले करना भी शामिल है । इसलिए, मेरा सुझाव (माइकल के अंतिम कोड और उनके अंतिम कोड के आपके अनुकूलन के साथ) वास्तव में CATCH
ब्लॉक को अक्सर नहीं मारा जाएगा । यह केवल दो सत्रों की स्थिति हो सकती है,ItemName
INSERT...SELECT
ठीक उसी क्षण जैसे कि दोनों सत्रों को ठीक उसी क्षण के लिए एक "सत्य" प्राप्त होता है WHERE NOT EXISTS
और इस प्रकार दोनों एक ही क्षण में सही करने का प्रयास करते INSERT
हैं। यह बहुत विशिष्ट परिदृश्य बहुत कम बार होता है या तो किसी मौजूदा का चयन करने ItemName
या किसी नए को सम्मिलित करने के दौरान ItemName
जब कोई अन्य प्रक्रिया सटीक समय पर ऐसा करने का प्रयास नहीं करती है ।
मन में सभी के साथ: मैं अपने दृष्टिकोण को क्यों पसंद करूं?
सबसे पहले, आइए देखें कि "क्रमबद्ध" दृष्टिकोण में लॉकिंग क्या होता है। जैसा कि ऊपर उल्लेख किया गया है, "लॉक" जो बंद हो जाता है वह मौजूदा कुंजी मूल्यों के दोनों तरफ निर्भर करता है जहां नया कुंजी मूल्य फिट होगा। रेंज की शुरुआत या अंत क्रमशः इंडेक्स की शुरुआत या अंत भी हो सकता है, अगर उस दिशा में कोई मौजूदा कुंजी मूल्य नहीं है। मान लें कि हमारे पास निम्नलिखित सूचकांक और कुंजियाँ हैं ( ^
जबकि $
इसके अंत का प्रतिनिधित्व करते हुए सूचकांक की शुरुआत का प्रतिनिधित्व करता है):
Range #: |--- 1 ---|--- 2 ---|--- 3 ---|--- 4 ---|
Key Value: ^ C F J $
यदि सत्र 55 एक प्रमुख मूल्य डालने का प्रयास करता है:
A
, तो # 1 (से लेकर ^
के लिए C
) बंद कर दिया जाता है: सत्र 56 के एक मूल्य नहीं डाल सकते B
हैं, भले ही अनोखी और वैध (अभी तक)। लेकिन सत्र 56 , और D
, के मूल्यों को सम्मिलित कर सकता है ।G
M
D
, तो # 2 (से लेकर C
के लिए F
) बंद कर दिया जाता है: सत्र 56 के एक मूल्य नहीं डाल सकते E
(अभी तक)। लेकिन सत्र 56 , और A
, के मूल्यों को सम्मिलित कर सकता है ।G
M
M
, तो # 4 (से लेकर J
के लिए $
) बंद कर दिया जाता है: सत्र 56 के एक मूल्य नहीं डाल सकते X
(अभी तक)। लेकिन सत्र 56 , और A
, के मूल्यों को सम्मिलित कर सकता है ।D
G
जैसे-जैसे अधिक महत्वपूर्ण मान जोड़े जाते हैं, कुंजी मानों के बीच की श्रृंखला संकरी होती जाती है, इसलिए एक ही समय में लड़ते हुए एक ही समय में डाले जा रहे कई मानों की संभावना / आवृत्ति कम हो जाती है। बेशक, यह एक बड़ी समस्या नहीं है, और सौभाग्य से यह एक ऐसी समस्या है जो वास्तव में समय के साथ कम हो जाती है।
मेरे दृष्टिकोण के साथ मुद्दा ऊपर वर्णित किया गया था: यह केवल तब होता है जब दो सत्र एक ही समय में एक ही कुंजी मान सम्मिलित करने का प्रयास करते हैं । इस संबंध में यह घटित होता है कि क्या होने की अधिक संभावना है: एक ही समय में दो अलग, फिर भी करीबी, प्रमुख मूल्यों का प्रयास किया जाता है या एक ही समय में एक ही कुंजी मूल्य का प्रयास किया जाता है? मुझे लगता है कि उत्तर आवेषण करने वाले ऐप की संरचना में निहित है, लेकिन आम तौर पर बोलते हुए मैं इसे अधिक संभावना मानूंगा कि दो अलग-अलग मूल्य जो कि एक ही श्रेणी को साझा करने के लिए होते हैं, सम्मिलित किए जा रहे हैं। लेकिन वास्तव में पता करने का एकमात्र तरीका दोनों ओपी सिस्टम पर परीक्षण करना होगा।
अगला, आइए दो परिदृश्यों पर विचार करें और प्रत्येक दृष्टिकोण उन्हें कैसे नियंत्रित करता है:
अद्वितीय मुख्य मूल्यों के लिए सभी अनुरोध:
इस स्थिति में, CATCH
मेरे सुझाव में ब्लॉक को कभी दर्ज नहीं किया गया है, इसलिए कोई "मुद्दा" नहीं है (यानी 4 ट्रान लॉग प्रविष्टियां और ऐसा करने में लगने वाला समय)। लेकिन, "धारावाहिक" दृष्टिकोण में, यहां तक कि सभी आवेषण अद्वितीय होने के साथ, एक ही श्रेणी में अन्य आवेषण को अवरुद्ध करने के लिए हमेशा कुछ क्षमता होगी (यद्यपि बहुत लंबे समय तक नहीं)।
एक ही समय में एक ही कुंजी मूल्य के लिए अनुरोधों की उच्च आवृत्ति:
इस मामले में - गैर-मौजूद प्रमुख मूल्यों के लिए आने वाले अनुरोधों के संदर्भ में विशिष्टता की बहुत कम डिग्री - CATCH
मेरे सुझाव में ब्लॉक नियमित रूप से दर्ज किया जाएगा। इसका प्रभाव यह होगा कि प्रत्येक असफल प्रविष्टि को ऑटो-रोलबैक में लाना होगा और ट्रांजेक्शन लॉग में 4 प्रविष्टियाँ लिखनी होंगी, जो कि हर बार एक मामूली प्रदर्शन है। लेकिन समग्र ऑपरेशन कभी भी विफल नहीं होना चाहिए (कम से कम इसके कारण नहीं)।
("अपडेटेड" दृष्टिकोण के पिछले संस्करण के साथ एक समस्या थी जिसने इसे गतिरोध से पीड़ित होने की अनुमति दी थी। इसे updlock
संबोधित करने के लिए एक संकेत जोड़ा गया था और अब यह गतिरोध नहीं मिलता है।)लेकिन, "क्रमबद्ध" दृष्टिकोण (यहां तक कि अद्यतन, अनुकूलित संस्करण) में, ऑपरेशन गतिरोध होगा। क्यों? क्योंकि serializable
व्यवहार केवल INSERT
उस सीमा में संचालन को रोकता है जिसे पढ़ा गया है और इसलिए लॉक किया गया है; यह SELECT
उस सीमा पर परिचालन को नहीं रोकता है ।
serializable
दृष्टिकोण, इस मामले में, कोई अतिरिक्त भूमि के ऊपर है लगता है, और मैं क्या सुझाव दे रहा हूँ की तुलना में थोड़ा बेहतर प्रदर्शन कर सकती है।
प्रदर्शन के संबंध में कई / सबसे अधिक चर्चाओं के कारण, ऐसे कई कारक होने के कारण जो परिणाम को प्रभावित कर सकते हैं, वास्तव में यह समझने का एकमात्र तरीका है कि कुछ प्रदर्शन कैसे करेंगे, लक्ष्य वातावरण में इसे आज़माने के लिए जहां यह चलेगा। उस समय यह राय का विषय नहीं होगा :)।