मुझे भारी मात्रा में INSERT की समस्या है जो मेरे SELECT संचालन को रोक रही हैं।
योजना
मेरे पास इस तरह की एक तालिका है:
CREATE TABLE [InverterData](
[InverterID] [bigint] NOT NULL,
[TimeStamp] [datetime] NOT NULL,
[ValueA] [decimal](18, 2) NULL,
[ValueB] [decimal](18, 2) NULL
CONSTRAINT [PrimaryKey_e149e28f-5754-4229-be01-65fafeebce16] PRIMARY KEY CLUSTERED
(
[TimeStamp] DESC,
[InverterID] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF
, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON
, ALLOW_PAGE_LOCKS = ON)
)
मेरे पास यह छोटी सहायक प्रक्रिया भी है, जो मुझे MERGE कमांड के साथ सम्मिलित करने या अपडेट (संघर्ष पर अद्यतन) करने की अनुमति देती है:
CREATE PROCEDURE [InsertOrUpdateInverterData]
@InverterID bigint, @TimeStamp datetime
, @ValueA decimal(18,2), @ValueB decimal(18,2)
AS
BEGIN
MERGE [InverterData] AS TARGET
USING (VALUES (@InverterID, @TimeStamp, @ValueA, @ValueB))
AS SOURCE ([InverterID], [TimeStamp], [ValueA], [ValueB])
ON TARGET.[InverterID] = @InverterID AND TARGET.[TimeStamp] = @TimeStamp
WHEN MATCHED THEN
UPDATE
SET [ValueA] = SOURCE.[ValueA], [ValueB] = SOURCE.[ValueB]
WHEN NOT MATCHED THEN
INSERT ([InverterID], [TimeStamp], [ValueA], [ValueB])
VALUES (SOURCE.[InverterID], SOURCE.[TimeStamp], SOURCE.[ValueA], SOURCE.[ValueB]);
END
प्रयोग
अब मैंने कई सर्वरों पर सेवा इंस्टेंसेस चलाए हैं जो [InsertOrUpdateInverterData]
प्रक्रिया को तेजी से कॉल करके बड़े पैमाने पर अपडेट करते हैं ।
एक वेबसाइट भी है जो [InverterData]
टेबल पर सेलेक्ट क्वेश्चन करती है।
मुसीबत
यदि मैं उस [InverterData]
टेबल पर सेलेक्ट क्वेश्चन करता हूं, जिसे वे अलग-अलग टाइमपासों में आगे बढ़ाते हैं, तो मेरे सेवा इंस्टेंसेस के INSERT उपयोग पर निर्भर करता है। अगर मैं सभी सर्विस इंस्टेंस को रोक देता हूं, तो सेलेक्ट लाइटनिंग-फास्ट है, अगर इंस्टेंस तेजी से इंसर्ट करता है तो सेलेक्ट्स वास्तव में स्लो हो जाते हैं या टाइमआउट कैंसिल भी हो जाते हैं।
प्रयास
मैं [sys.dm_tran_locks]
लॉकिंग प्रक्रियाओं को खोजने के लिए मेज पर कुछ चयन कर रहा हूं , जैसे
SELECT
tl.request_session_id,
wt.blocking_session_id,
OBJECT_NAME(p.OBJECT_ID) BlockedObjectName,
h1.TEXT AS RequestingText,
h2.TEXT AS BlockingText,
tl.request_mode
FROM sys.dm_tran_locks AS tl
INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address = wt.resource_address
INNER JOIN sys.partitions AS p ON p.hobt_id = tl.resource_associated_entity_id
INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id
INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id
CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1
CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2
यह परिणाम है:
एस = साझा किया गया। होल्डिंग सत्र को संसाधन तक साझा पहुंच प्रदान की जाती है।
सवाल
चयन [InsertOrUpdateInverterData]
प्रक्रिया केवल MERGE कमांड का उपयोग करने वाली प्रक्रिया से अवरुद्ध क्यों हैं ?
क्या मुझे परिभाषित आइसोलेशन मोड के साथ किसी प्रकार के लेनदेन का उपयोग करना है [InsertOrUpdateInverterData]
?
अपडेट 1 (@Paul से संबंधित प्रश्न)
[InsertOrUpdateInverterData]
निम्नलिखित आंकड़ों के बारे में MS-SQL सर्वर आंतरिक रिपोर्टिंग के आधार पर :
- औसत CPU-समय: 0.12ms
- औसत पढ़ने की प्रक्रिया: 5.76 प्रति / से
- औसत लिखने की प्रक्रिया: 0.4 प्रति / एस
इसके आधार पर ऐसा लगता है कि MERGE कमांड ज्यादातर पढ़ने के संचालन में व्यस्त है जो तालिका को बंद कर देगा? (?)
अपडेट 2 (@Paul से संबंधित प्रश्न)
[InverterData]
तालिका के रूप में भंडारण आँकड़े निम्नलिखित है:
- डेटा स्पेस: 26,901.86 एमबी
- पंक्ति गणना: 131,827,749
- विभाजन: सच
- विभाजन की संख्या: 62
यहाँ (सभी) पूर्ण sp_WhoIsActive परिणाम सेट है:
SELECT
आदेश
- dd hh: mm: ss.mss: 00 00: 01: 01.930
- session_id: 73
- Wait_info: (12629ms) LCK_M_S
- सीपीयू: 198
- block_session_id: 146
- पढ़ता है: 99,368
- लिखते हैं: 0
- स्थिति: निलंबित
- open_tran_count: 0
ब्लॉकिंग [InsertOrUpdateInverterData]
कमांड
- dd hh: mm: ss.mss: 00 00: 00: 00.330
- session_id: 146
- Wait_info: NULL
- सीपीयू: 3,972
- block_session_id: NULL
- पढ़ता है: 376,95
- लिखते हैं: 126
- स्थिति: नींद
- open_tran_count: 1
([TimeStamp] DESC, [InverterID] ASC)
दिखता संकुल अनुक्रमणिका के लिए एक अजीब विकल्प की तरह। मेरा मतलबDESC
हिस्सा है।