เห็นได้ชัดว่าฟังก์ชั่นการประกอบ CLR ของฉันทำให้เกิดการหยุดชะงัก


9

แอปพลิเคชันของเราต้องทำงานอย่างเท่าเทียมกันกับฐานข้อมูล Oracle หรือฐานข้อมูล Microsoft SQL Server เพื่ออำนวยความสะดวกในเรื่องนี้เราได้สร้าง UDF จำนวนหนึ่งเพื่อทำให้ไวยากรณ์การสืบค้นของเราเป็นเนื้อเดียวกัน ตัวอย่างเช่น SQL Server มี GETDATE () และ Oracle มี SYSDATE พวกเขาทำหน้าที่เดียวกัน แต่เป็นคำที่ต่างกัน เราเขียน wrapper UDF ชื่อ NOW () สำหรับทั้งสองแพลตฟอร์มซึ่งล้อมรอบไวยากรณ์เฉพาะแพลตฟอร์มที่เกี่ยวข้องในชื่อฟังก์ชันทั่วไป เรามีฟังก์ชั่นอื่น ๆ ซึ่งบางส่วนไม่ทำอะไรเลย แต่มีอยู่เพียงเพื่อความเป็นเนื้อเดียวกัน น่าเสียดายที่ค่าใช้จ่ายนี้สำหรับ SQL Server UDF สเกลาร์แบบอินไลน์สร้างความหายนะต่อประสิทธิภาพและปิดการใช้งานความขนานอย่างสมบูรณ์ เป็นทางเลือกเราเขียนฟังก์ชันการประกอบ CLR เพื่อให้บรรลุเป้าหมายเดียวกัน เมื่อเราปรับใช้สิ่งนี้กับลูกค้าพวกเขาเริ่มประสบกับการหยุดชะงักบ่อยครั้ง ลูกค้ารายนี้ใช้การจำลองแบบและเทคนิคความพร้อมใช้งานสูงและฉันสงสัยว่ามีการโต้ตอบบางอย่างเกิดขึ้นที่นี่หรือไม่ ฉันไม่เข้าใจว่าการแนะนำฟังก์ชัน CLR จะทำให้เกิดปัญหาเช่นนี้ได้อย่างไร สำหรับการอ้างอิงฉันได้รวมข้อกำหนด UDF สเกลาร์ต้นฉบับไว้รวมถึงข้อกำหนดการแทนที่ CLR ใน C # และการประกาศ SQL สำหรับมัน ฉันยังมี deadlock XML ที่ฉันสามารถให้ได้หากมีสิ่งนั้นช่วย

UDF ดั้งเดิม

CREATE FUNCTION [fn].[APAD]
(
    @Value VARCHAR(4000)
    , @tablename VARCHAR(4000) = NULL
    , @columnname VARCHAR(4000) = NULL
)

RETURNS VARCHAR(4000)
WITH SCHEMABINDING
AS

BEGIN
    RETURN LTRIM(RTRIM(@Value))
END
GO

ฟังก์ชั่นการประกอบ CLR

[SqlFunction(IsDeterministic = true)]
public static string APAD(string value, string tableName, string columnName)
{
    return value?.Trim();
}

การประกาศเซิร์ฟเวอร์ SQL สำหรับฟังก์ชัน CLR

CREATE FUNCTION [fn].[APAD]
(
    @Value NVARCHAR(4000),
    @TableName NVARCHAR(4000),
    @ColumnName NVARCHAR(4000)
) RETURNS NVARCHAR(4000)
AS
EXTERNAL NAME ASI.fn.APAD
GO

9
ฟังก์ชัน CLR สเกลาร์แบบกำหนดได้ไม่ควรนำไปสู่การหยุดชะงัก แน่นอนว่าฟังก์ชัน CLR ที่อ่านฐานข้อมูลอาจ คุณควรรวม XML การหยุดชะงักในคำถามของคุณ
David Browne - Microsoft

คำตอบ:


7

คุณใช้ SQL Server รุ่นใด

ฉันจำได้ว่าเคยเห็นพฤติกรรมการเปลี่ยนแปลงเล็กน้อยใน SQL Server 2017 เมื่อไม่นานมานี้ ฉันจะต้องย้อนกลับไปดูว่าฉันสามารถหาตำแหน่งที่ฉันจดบันทึกได้หรือไม่ แต่ฉันคิดว่ามันต้องเกี่ยวข้องกับการล็อค schema ที่เริ่มต้นเมื่อมีการเข้าถึงวัตถุ SQLCLR

ในขณะที่ฉันกำลังมองหาที่ฉันจะพูดต่อไปนี้เกี่ยวกับวิธีการของคุณ:

  1. โปรดใช้Sql*ประเภทสำหรับพารามิเตอร์อินพุตประเภทส่งคืน คุณควรจะใช้แทนSqlString จะคล้ายกับสตริง nullable (ของคุณแต่มันก็มีฟังก์ชั่นอื่น ๆ ที่สร้างขึ้นในที่เป็น SQL Server เฉพาะ. ทุกประเภทมีคุณสมบัติที่ผลตอบแทนที่คาดว่าประเภท .NET (เช่นผลตอบแทน, ผลตอบแทน, ผลตอบแทน, ฯลฯ )stringSqlStringvalue?Sql*ValueSqlString.ValuestringSqlInt32intSqlDateTimeDateTime
  2. ฉันอยากจะแนะนำกับวิธีการทั้งหมดนี้เพื่อเริ่มต้นด้วยไม่ว่าจะมีการหยุดชะงักเกี่ยวข้องหรือไม่ ฉันพูดแบบนี้เพราะ:

    1. ถึงแม้จะมี SQLCLR UDF ที่กำหนดได้แล้วที่สามารถมีส่วนร่วมในแผนคู่ขนานได้ แต่คุณก็มีแนวโน้มที่จะได้รับผลการปฏิบัติงานที่ยอดเยี่ยมสำหรับการจำลองฟังก์ชั่นในตัวที่เรียบง่าย
    2. SQLCLR API VARCHARไม่อนุญาตให้ คุณตกลงกับการแปลงทุกอย่างเป็นนัยNVARCHARแล้วกลับไปVARCHARใช้การดำเนินการอย่างง่ายอีกครั้งหรือไม่?
    3. SQLCLR API ไม่อนุญาตให้มีการโหลดมากเกินไปดังนั้นคุณอาจต้องการฟังก์ชั่นหลายรุ่นที่อนุญาตสำหรับลายเซ็นที่แตกต่างกันใน T-SQL และ / หรือ PL / SQL
    4. คล้ายกับที่ไม่อนุญาตให้ใช้งานมากเกินไปมีความแตกต่างอย่างมากระหว่างNVARCHAR(4000)และNVARCHAR(MAX): MAXประเภท (มีแม้แต่หนึ่งเดียวของพวกเขาในลายเซ็น) ทำให้การเรียก SQLCLR ใช้เวลาสองครั้งตราบใดที่ไม่มีMAXประเภทใด ๆในลายเซ็น (ฉันเชื่อว่านี่ถือ จริงสำหรับVARBINARY(MAX)vs VARBINARY(4000)เช่นกัน) ดังนั้นคุณต้องตัดสินใจระหว่าง:
      • ใช้NVARCHAR(MAX)เพื่อให้มี API ที่ง่ายขึ้นเท่านั้น แต่ให้ประสิทธิภาพที่ยอดเยี่ยมเมื่อคุณใช้ข้อมูลสตริง 8000 หรือน้อยกว่านั้นหรือ
      • การสร้างรูปแบบสองรูปแบบสำหรับฟังก์ชั่นสตริงทั้งหมด / ส่วนใหญ่ / จำนวนมาก: อันที่มีMAXประเภทและอีกหนึ่งไม่มี (สำหรับเมื่อคุณรับประกันว่าจะไม่เกิน 8000 ไบต์ของข้อมูลสตริงเข้าหรือออก) นี่เป็นวิธีที่ฉันเลือกที่จะใช้สำหรับฟังก์ชั่นส่วนใหญ่ในห้องสมุดSQL #ของฉัน: มีTrim()ฟังก์ชั่นที่น่าจะมีหนึ่งMAXประเภทหรือมากกว่าและTrim4k()รุ่นที่ไม่เคยมีMAXประเภทใดในสคีมาชุดลายเซ็นหรือชุดผลลัพธ์ เวอร์ชั่น "4k" นั้นมีประสิทธิภาพมากกว่าอย่างแน่นอน
    5. คุณไม่ได้ระมัดระวังที่จะเลียนแบบฟังก์ชันการทำงานตามตัวอย่างในคำถาม LTRIMและRTRIMตัดแต่งเฉพาะช่องว่างในขณะที่. NET String.Trim()ย่อพื้นที่สีขาว (อย่างน้อยพื้นที่แท็บและขึ้นบรรทัดใหม่) ตัวอย่างเช่น:

        PRINT LTRIM(RTRIM(N'      a       '));
    6. นอกจากนี้ฉันเพิ่งสังเกตเห็นว่าฟังก์ชั่นของคุณทั้งใน T-SQL และ C # ใช้พารามิเตอร์อินพุต 1 ใน 3 เท่านั้น นี่เป็นเพียงการพิสูจน์แนวคิดหรือรหัส redacted หรือไม่

1. ขอบคุณสำหรับเคล็ดลับในการใช้ประเภทของ SQL ฉันจะทำการเปลี่ยนแปลงนั้นทันที 2. มีกองกำลังภายนอกที่ทำงานที่นี่ซึ่งจำเป็นต้องใช้พวกเขา ฉันไม่ได้ตื่นเต้นเกี่ยวกับมัน แต่เชื่อฉันมันจะดีกว่าทางเลือก คำถามเดิมของฉันมีคำอธิบายเล็กน้อยว่าทำไมฟังก์ชั่น asinine ดูเหมือนมีอยู่และกำลังถูกใช้งาน
Russ Suter

@RussSuter เข้าใจอีกครั้ง: แรงภายนอก ฉันแค่ชี้ให้เห็นถึงข้อผิดพลาดบางอย่างที่อาจไม่เป็นที่ทราบเมื่อมีการตัดสินใจ ไม่ว่าจะด้วยวิธีใดฉันไม่สามารถค้นหาบันทึกย่อของฉันหรือจำลองสถานการณ์จากรายละเอียดบางอย่างที่ฉันจำได้ ฉันเพิ่งจำบางสิ่งที่เปลี่ยนแปลงแน่นอนในปี 2560 เกี่ยวกับการทำธุรกรรมและการเรียกรหัสจากแอสเซมบลีและรู้สึกรำคาญจริง ๆเพราะดูเหมือนว่าการเปลี่ยนแปลงที่ไม่จำเป็นสำหรับสิ่งที่แย่กว่านั้นคือฉันต้องทำงานกับสิ่งที่ฉันทดสอบ ปรับในรุ่นก่อน ดังนั้นโปรดโพสต์ลิงก์ในคำถามไปยัง XML การหยุดชะงัก
โซโลมอน Rutzky

ขอบคุณสำหรับข้อมูลเพิ่มเติม นี่คือลิงค์ไปยัง XML: dropbox.com/s/n9w8nsdojqdypqm/deadlock17.xml?dl=0
Russ Suter

@RussSuter คุณเคยลองใช้ T-SQL แล้วหรือยัง? ดู XML deadlock (ซึ่งไม่ใช่เรื่องง่ายเพราะเป็นบรรทัดเดียว - บรรทัดใหม่ทั้งหมดถูกลบออกไปอย่างใดอย่างหนึ่ง) ดูเหมือนว่าจะเป็นชุดของ PAGE Lock ระหว่างเซสชันที่ 60 และ 78 มี 8 หน้าที่ถูกล็อคระหว่างทั้งสองเซสชัน: 3 ต่อหนึ่ง SPID และ 5 สำหรับอีกอัน แต่ละรหัสกระบวนการที่แตกต่างกันดังนั้นนี่คือปัญหาของการขนาน หากสิ่งนี้เกี่ยวข้องกับ SQLCLR อาจเป็นข้อเท็จจริงที่ว่า SQLCLR ไม่ได้ป้องกันการขนานกัน นี่คือเหตุผลที่ฉันถามว่าคุณลองใส่ฟังก์ชั่นง่าย ๆ แบบอินไลน์หรือไม่ซึ่งอาจแสดงการหยุดชะงัก
โซโลมอน Rutzky
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.