เหตุใดข้อผิดพลาดการสืบค้นที่ตั้งค่าผลลัพธ์ว่างใน SQL Server 2012


31

เมื่อเรียกใช้แบบสอบถามต่อไปนี้ใน MS SQL Server 2012 แบบสอบถามที่สองล้มเหลว แต่ไม่ใช่แบบสอบถามแรก นอกจากนี้เมื่อเรียกใช้โดยไม่มีส่วนคำสั่งทั้งสองข้อจะล้มเหลว ฉันแพ้ทำไมทั้งสองล้มเหลวเนื่องจากทั้งคู่ควรมีชุดผลลัพธ์ว่างเปล่า ความช่วยเหลือ / ความเข้าใจใด ๆ ที่มีความนิยม

create table #temp
(id     int primary key)

create table #temp2
(id     int)

select 1/0
from #temp
where id = 1

select 1/0
from #temp2
where id = 1

คำตอบ:


39

ดูเริ่มต้นที่แผนการดำเนินการแสดงว่านิพจน์1/0ถูกกำหนดในตัวดำเนินการคำนวณสเกลาร์:

แผนกราฟิก

ตอนนี้ถึงแม้ว่าแผนการดำเนินการจะเริ่มดำเนินการในด้านซ้ายสุด, ซ้ำเรียกร้องOpenและGetRowวิธีการเกี่ยวกับการ iterators เด็กเพื่อให้ได้ผลลัพธ์, SQL Server 2005 และต่อมามีการเพิ่มประสิทธิภาพโดยการแสดงออกมักจะเป็นเพียงกำหนดโดย Compute เกลากับการประเมินผลการเลื่อนไปก่อนจนกว่าภายหลัง การดำเนินการต้องใช้ผลลัพธ์ :

คำนวณตัวดำเนินการสเกลาร์ที่ปรากฏใน Showplans ที่สร้างโดย SET STATISTICS XML อาจไม่มีองค์ประกอบ RunTimeInformation  ใน Showplans แบบกราฟิก, แถวที่แท้จริง, การตอบกลับจริงและการกรอกลับจริงอาจหายไปจากหน้าต่างคุณสมบัติเมื่อเลือกตัวเลือกรวมการดำเนินการตามแผนจริงใน SQL Server Management Studio  เมื่อสิ่งนี้เกิดขึ้นหมายความว่าแม้ว่าตัวดำเนินการเหล่านี้จะถูกใช้ในแผนแบบสอบถามที่คอมไพล์ แต่งานของพวกเขาถูกดำเนินการโดยตัวดำเนินการอื่นในแผนแบบสอบถามแบบรันไทม์  นอกจากนี้โปรดทราบว่าจำนวนการเรียกใช้งานในเอาต์พุต Showplan ที่สร้างโดย SET STATISTICS PROFILE เท่ากับผลรวมของการเชื่อมโยงและย้อนกลับใน Showplans ที่สร้างโดย SET STATISTICS XML  จาก: MSDN Books Online

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

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

Showplan XML

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

select 1/0 * CONVERT(integer, @@DBTS)
from #temp
where id = 1

select 1/0
from #temp2
where id = 1

ตอนนี้แผนแรกยังมีการอ้างอิงนิพจน์คงที่และแบบสอบถามทั้งสองผลิตข้อความแสดงข้อผิดพลาด XML สำหรับแบบสอบถามแรกประกอบด้วย:

การแสดงออกอย่างต่อเนื่อง

ข้อมูลเพิ่มเติม: คำนวณสเกลาร์นิพจน์และประสิทธิภาพ


21

ฉันจะคาดเดาอย่างชาญฉลาด (และในกระบวนการอาจดึงดูดกูรู SQL Server ที่อาจให้คำตอบโดยละเอียด)

แบบสอบถามแรกเข้าใกล้การดำเนินการเป็น:

  1. สแกนดัชนีคีย์หลัก
  2. ค้นหาค่าในตารางข้อมูลที่จำเป็นสำหรับแบบสอบถาม

มันเลือกเส้นทางนี้เพราะคุณมีส่วนwhereคำสั่งในคีย์หลัก ไม่เคยไปถึงขั้นตอนที่สองดังนั้นการสืบค้นจึงไม่ล้มเหลว

ที่สองไม่มีคีย์หลักให้ทำงานดังนั้นจึงเข้าใกล้คิวรีดังนี้:

  1. ทำการสแกนตารางแบบเต็มของข้อมูลและดึงค่าที่จำเป็น

หนึ่งในค่าเหล่านั้นเป็น1/0สาเหตุของปัญหา

นี่คือตัวอย่างของ SQL Server ที่ปรับการสืบค้นให้เหมาะสม ส่วนใหญ่นี่เป็นสิ่งที่ดี SQL Server จะย้ายเงื่อนไขจากselectในการดำเนินการสแกนตาราง ซึ่งมักจะบันทึกขั้นตอนในการประเมินผลของแบบสอบถาม

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


1
+1 ไม่มีเงื่อนงำถ้าคุณพูดถูก แต่คำตอบที่ดีที่สุดที่ฉันเห็นคือความแตกต่างเพียงอย่างเดียวคือคีย์หลัก

1
@GordonLinoff Paul Randal เพิ่งยืนยันผ่าน Twitter ว่าการตอบกลับของคุณได้รับการแก้ไข
SchmitzIT

4
@Still, ลำดับการดำเนินการจริง, แตกต่างกัน, แต่ไม่ควรนำไปสู่ข้อผิดพลาดเช่นนั้น
ypercubeᵀᴹ

7
@ypercube Erland Sommarskog จะเห็นด้วยกับคุณ (เชื่อมต่อรายการ)
พอลไวท์พูดว่า GoFundMonica

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