ประสิทธิภาพของเซิร์ฟเวอร์ SQL ที่เชื่อมโยงกับเซิร์ฟเวอร์: เหตุใดแบบสอบถามระยะไกลจึงมีราคาแพง


14

ฉันมีเซิร์ฟเวอร์ฐานข้อมูลสองตัวเชื่อมต่อผ่านเซิร์ฟเวอร์ที่เชื่อมโยง ทั้งสองเป็นฐานข้อมูล SQL Server 2008R2 และการเชื่อมต่อเซิร์ฟเวอร์ที่เชื่อมโยงจะทำผ่านลิงค์ "SQL Server" ปกติโดยใช้บริบทความปลอดภัยของการเข้าสู่ระบบปัจจุบัน เซิร์ฟเวอร์ที่เชื่อมโยงนั้นมีทั้งในดาต้าเซ็นเตอร์เดียวกันดังนั้นการเชื่อมต่อจึงไม่เป็นปัญหา

ฉันใช้แบบสอบถามต่อไปนี้เพื่อตรวจสอบว่าค่าของคอลัมน์identifierใดที่พร้อมใช้งานจากระยะไกล แต่ไม่ใช่ภายในเครื่อง

SELECT 
    identifier 
FROM LinkedServer.RemoteDb.schema.[TableName]

EXCEPT

SELECT DISTINCT
    identifier 
FROM LocalDb.schema.[TableName] 

identifierบนโต๊ะทั้งสองเป็นดัชนีที่ไม่ใช่คลัสเตอร์ในคอลัมน์ ในพื้นที่มีแถว 2.6M แถวจากระยะไกลเพียง 54 แต่เมื่อมองไปที่แผนแบบสอบถาม 70% ของเวลาดำเนินการจะถูกใช้เพื่อ "ประมวลผลแบบสอบถามระยะไกล" นอกจากนี้เมื่อศึกษาแผนคิวรีที่สมบูรณ์จำนวนแถวท้องถิ่นโดยประมาณนั้น1แทน2695380(ซึ่งคือจำนวนแถวโดยประมาณเมื่อเลือกเฉพาะคิวรีที่มาหลังจากนั้นEXCEPT) แผนการดำเนินการ เมื่อดำเนินการค้นหานี้จะใช้เวลานานแน่นอน

มันทำให้ฉันประหลาดใจ: ทำไมถึงเป็นอย่างนี้? การประมาณค่าเป็น "เพียงแค่" ปิดหรือมีการสอบถามระยะไกลบนเซิร์ฟเวอร์ที่เชื่อมโยงที่มีราคาแพงจริงๆ?


2
BTW: มันคือ "จำนวนการประหารชีวิตโดยประมาณ" ที่คุณควรมองหาเพื่อค้นหาดัชนี จำนวนแถวโดยประมาณคือเอาท์พุทแถวต่อการดำเนินการซึ่งจะไม่เกี่ยวข้องกับจำนวนแถวในตารางเองยกเว้นว่าแผนสแกนเต็ม
Martin Smith

คำตอบ:


9

แผนการที่คุณมีในขณะนี้ดูเหมือนแผนการที่เหมาะสมที่สุดสำหรับฉัน

ฉันไม่เห็นด้วยกับการยืนยันในคำตอบอื่น ๆ ที่กำลังส่งแถว 2.6M ไปยังเซิร์ฟเวอร์ระยะไกล

แผนดูเหมือนกับฉันสำหรับแต่ละแถว 54 ที่ส่งคืนจากแบบสอบถามแบบรีโมตซึ่งกำลังดำเนินการค้นหาดัชนีในตารางท้องถิ่นของคุณเพื่อพิจารณาว่าตรงกันหรือไม่ นี่เป็นแผนการที่ดีที่สุด

การแทนที่ด้วยการเข้าร่วมแบบแฮชหรือการรวมแบบผสานจะเป็นการต่อต้านเนื่องจากขนาดของตารางและการเพิ่ม#tempตารางกลางเพียงแค่เพิ่มขั้นตอนเพิ่มเติมที่ดูเหมือนจะไม่ให้ประโยชน์ใด ๆ แก่คุณ


6

การเชื่อมต่อกับทรัพยากรระยะไกลมีราคาแพง ระยะเวลา

หนึ่งในการดำเนินการที่แพงที่สุดในสภาพแวดล้อมการเขียนโปรแกรมใด ๆ คือเครือข่าย IO (แม้ว่าดิสก์ IO มักจะแคระมัน)

สิ่งนี้ขยายไปถึงเซิร์ฟเวอร์ที่เชื่อมโยงระยะไกล เซิร์ฟเวอร์ที่เรียกใช้เซิร์ฟเวอร์ที่เชื่อมโยงระยะไกลนั้นจำเป็นต้องสร้างการเชื่อมต่อก่อนจากนั้นจึงต้องดำเนินการค้นหาบนเซิร์ฟเวอร์ระยะไกลส่งคืนผลลัพธ์และปิดการเชื่อมต่อ ทั้งหมดนี้ใช้เวลาผ่านเครือข่าย


คุณควรจัดโครงสร้างคิวรีของคุณในลักษณะที่คุณถ่ายโอนข้อมูลขั้นต่ำข้ามสาย อย่าคาดหวังว่า DB จะปรับให้เหมาะสมสำหรับคุณ

ถ้าฉันจะเขียนแบบสอบถามนี้ฉันจะเลือกข้อมูลระยะไกลลงในตัวแปรตาราง (หรือลงในตารางชั่วคราว) แล้วใช้สิ่งนี้ร่วมกับตารางท้องถิ่น สิ่งนี้ทำให้มั่นใจได้ว่าข้อมูลที่จำเป็นต้องมีการโอนเท่านั้น

แบบสอบถามที่คุณกำลังเรียกใช้สามารถส่งแถว 2.6M ไปยังเซิร์ฟเวอร์ระยะไกลได้อย่างง่ายดายเพื่อประมวลผลEXCEPTส่วนคำสั่ง


ตกลงดังนั้นจึงมีค่าใช้จ่ายเริ่มต้นสูงในการตั้งค่าการเชื่อมต่อ แบบสอบถามจะต้องมีการส่งประมวลผลจากระยะไกล (ไม่จำเป็นต้องใช้เครือข่ายสำหรับหนึ่ง) และในที่สุดก็ส่งผลลัพธ์และประมวลผล แต่จะใช้เวลาไม่กี่นาทีในการส่งข้อมูลผ่านการเชื่อมต่อเครือข่าย
vstrien

@vstrien - มันอาจ ขึ้นอยู่กับการเชื่อมต่อเครือข่ายเวลาแฝงความอิ่มตัวและปัจจัยอื่น ๆ จุดที่เป็น - มันไม่ได้กำหนด

@vstrien - เพิ่มข้อมูลเพิ่มเติมในคำตอบของฉัน ฉันเชื่อว่าแบบสอบถามตามที่เขียนจะส่งแถวท้องถิ่นไปยังเซิร์ฟเวอร์ระยะไกลเพื่อการประมวลผล

2
คุณอนุมานข้อเท็จจริงที่ว่ามันส่งแถว 2.6M ไปยังเซิร์ฟเวอร์ระยะไกลได้อย่างไร ฉันไม่ได้มีประสบการณ์กับแผนกับตัวดำเนินการแบบสอบถามระยะไกลมาก แต่ดูเหมือนว่า 54 แถวกำลังออกมาจากตัวดำเนินการแบบสอบถามระยะไกลแล้วมันกำลังทำการต่อต้านกึ่งรวมกับตารางท้องถิ่น
Martin Smith

2
@Lieven - อาจเป็นเหตุผล แต่ไม่คิดว่าถูกต้องจากแผนที่แสดง
Martin Smith

1

ฉันไม่ใช่ผู้เชี่ยวชาญ แต่ถ้าคุณใช้สหภาพยกเว้นหรือตัดกันคุณไม่จำเป็นต้องใช้ "Distinct" ทั้งนี้ขึ้นอยู่กับค่าจาก LocalDb.schema [TableName] สามารถปรับปรุงประสิทธิภาพการสืบค้นได้

SELECT 
    identifier 
FROM LinkedServer.RemoteDb.schema.[TableName]

EXCEPT

SELECT 
    identifier 
FROM LocalDb.schema.[TableName]

0

Oded ถูกต้องปัญหาด้านประสิทธิภาพเกิดจากการส่งแถว 2.6M ไปยังเซิร์ฟเวอร์ระยะไกลของคุณ

เมื่อต้องการแก้ไขปัญหานี้คุณสามารถบังคับให้ส่งข้อมูลระยะไกล (54 แถว) ให้คุณโดยใช้ temp หรือในตารางหน่วยความจำ

ใช้ตารางชั่วคราว

SELECT  identifier 
INTO    #TableName
FROM    LinkedServer.RemoteDb.schema.[TableName]

SELECT  identifier
FROM    #TableName
EXCEPT
SELECT  DISTINCT identifier 
FROM    LocalDb.schema.[TableName] 

DROP    #TableName

การใช้ตารางชั่วคราวอาจช่วยในการประมาณค่าระดับความสำคัญในเหตุการณ์ใด ๆ แม้ว่าการวนซ้ำซ้อนกันจะดูสมเหตุสมผลสำหรับ 54 แถวเท่านั้น
Martin Smith

การใช้ตารางชั่วคราวทำงานได้ถูกต้องกับ 54 แถว; แต่ในกรณีที่มีตารางขนาดใหญ่ทั้งสองด้านจะไม่สามารถทำได้อีกต่อไป โซลูชันของคุณจะเป็นอะไรสำหรับตาราง "ใหญ่" สองขนาดเท่ากัน? สร้าง UserTable ในฐานข้อมูลอื่นหรือไม่
vstrien

1
@vstrien - ไม่มีวิธีแก้ปัญหาที่ดีสำหรับตารางขนาดใหญ่ขนาดเท่ากันสองตัว บางทีการสร้างมุมมองแบบพาร์ติชันแบบกระจายเป็นที่สนใจของคุณ แต่ฉันไม่มีประสบการณ์ใด ๆ กับมัน
Lieven Keersmaekers

0

ฉันคิดว่าคุณดีกว่าการจำลองตารางระยะไกลไปยังเซิร์ฟเวอร์ที่คุณทำการสืบค้นจากนั้นเรียกใช้ SQL ของคุณทั้งหมดในเครื่อง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.