SQL Server รู้ว่าภาคแสดงมีความสัมพันธ์กันอย่างไร


15

ในขณะที่การวิเคราะห์แบบสอบถาม SQL Server 2008 R2 ด้วยการประมาณค่า cardinality ที่ไม่ดี (แม้จะมีการทำดัชนีอย่างง่ายสถิติที่ทันสมัย ​​ฯลฯ ) และด้วยเหตุนี้แผนการสืบค้นที่ไม่ดีฉันพบบทความ KB ที่เกี่ยวข้องบางที: การ แก้ไข: ประสิทธิภาพแย่เมื่อคุณเรียกใช้แบบสอบถาม ที่ประกอบด้วยสหสัมพันธ์และเพรดิเคตใน SQL Server 2008 หรือใน SQL Server 2008 R2 หรือใน SQL Server 2012

ฉันสามารถเดาได้ว่าบทความ KB หมายถึงอะไรโดย "มีความสัมพันธ์" เช่นภาคแสดงข้อ 2 และภาคส่วน # 1 ส่วนใหญ่กำหนดเป้าหมายไปที่แถวเดียวกัน

แต่ฉันไม่รู้ว่า SQL Server รู้เกี่ยวกับสหสัมพันธ์เหล่านี้อย่างไร ตารางต้องการดัชนีหลายคอลัมน์ที่มีคอลัมน์จากเพรดิเคตทั้งสองหรือไม่ SQL ใช้สถิติเพื่อตรวจสอบว่าค่าจากคอลัมน์หนึ่งมีความสัมพันธ์กับอีกคอลัมน์หนึ่งหรือไม่? หรือมีวิธีอื่นที่ใช้?

ฉันขอสิ่งนี้ด้วยสองเหตุผล:

  1. เพื่อกำหนดว่าตารางและแบบสอบถามใดของฉันอาจได้รับการปรับปรุงโดยใช้โปรแกรมแก้ไขด่วนนี้
  2. หากต้องการทราบว่าฉันควรทำอย่างไรในการจัดทำดัชนีสถิติ ฯลฯ เพื่อให้มีผลกับ # 1

คำตอบ:


20

พิจารณาคำถามและแผนการดำเนินการของAdventureWorks ที่แสดงด้านล่าง ANDแบบสอบถามประกอบด้วยภาคการเชื่อมต่อกับ การประเมินความสำคัญของเครื่องมือเพิ่มประสิทธิภาพคือแถวที่41,211 :

-- Estimate 41,211 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

แผนการดำเนินการเริ่มต้น

ใช้สถิติเริ่มต้น

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

การแยกคิวรีออกเป็นสองส่วนทำให้การคำนวณง่ายขึ้นที่จะเห็น:

-- Estimate 68,336.4 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336;

ตารางประวัติการทำธุรกรรมประกอบด้วยจำนวน 113,443 แถวดังนั้นการประมาณการ 68,336.4 จึงเป็นตัวเลือกที่ 68336.4 / 113443 = 0.60238533สำหรับภาคแสดงนี้ การประมาณนี้ได้มาโดยใช้ข้อมูลฮิสโตแกรมสำหรับTransactionIDคอลัมน์และค่าคงที่ที่ระบุในแบบสอบถาม

-- Estimate 68,413 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

กริยานี้มีการคัดสรรประมาณ 68,413.0 / 113,443 = 0.60306056 อีกครั้งมันถูกคำนวณจากค่าคงที่ของภาคแสดงและฮิสโตแกรมของTransactionDateวัตถุสถิติ

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

0.60238533 * 0.60306056 * 113443 = 41210.987

หลังการปัดเศษนี่เป็นประมาณการ 41,211 ที่เห็นในแบบสอบถามต้นฉบับ (เครื่องมือเพิ่มประสิทธิภาพยังใช้คณิตศาสตร์จุดลอยภายใน)

ไม่ใช่การประเมินที่ยอดเยี่ยม

TransactionIDและTransactionDateคอลัมน์มีความสัมพันธ์ใกล้ชิดในข้อมูล AdventureWorks ที่กำหนด (เป็นกุญแจ monotonically เพิ่มขึ้นและคอลัมน์วันมักจะทำ) ความสัมพันธ์นี้หมายความว่ามีการละเมิดสมมติฐานที่เป็นอิสระ ดังนั้นแผนการสืบค้นข้อมูลหลังการประมวลผลจะแสดงแถว 68,095 มากกว่าระดับ 41,211 โดยประมาณ:

แผนการหลังการดำเนินการ

ติดตามสถานะ 4137

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

-- Estimate 68,336.4
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13'
OPTION (QUERYTRACEON 4137);

จำได้ว่าTransactionIDคำกริยาเพียงอย่างเดียวประมาณ 68,336.4 แถวและเพรดิเคตTransactionDateเพียงอย่างเดียวประมาณ 68,413 แถว เครื่องมือเพิ่มประสิทธิภาพได้เลือกค่าประมาณสองค่านี้ต่ำกว่าการเลือกแบบทวีคูณ

นี่เป็นเพียงวิธีแก้ปัญหาที่แตกต่างกัน แต่เป็นวิธีที่สามารถช่วยปรับปรุงการประมาณการสำหรับข้อความค้นหาที่เกี่ยวข้องกับภาคANDแสดงได้ เพรดิเคตแต่ละตัวจะพิจารณาความสัมพันธ์ที่เป็นไปได้และมีการปรับอื่น ๆ ที่ทำขึ้นเมื่อมีหลายANDประโยคที่เกี่ยวข้อง แต่ตัวอย่างนั้นทำหน้าที่แสดงพื้นฐานของมัน

สถิติหลายคอลัมน์

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

CREATE STATISTICS
    [stats Production.TransactionHistory TransactionID TransactionDate]
ON Production.TransactionHistory
    (TransactionID, TransactionDate);

CREATE STATISTICS
    [stats Production.TransactionHistory TransactionDate TransactionID]
ON Production.TransactionHistory
    (TransactionDate, TransactionID);

การรับหนึ่งในนั้นเราสามารถเห็นได้ว่าข้อมูลพิเศษเพียงอย่างเดียวคือระดับความหนาแน่นที่เพิ่มขึ้นของ 'ทั้งหมด' ฮิสโตแกรมยังคงมีข้อมูลรายละเอียดเกี่ยวกับTransactionDateคอลัมน์เท่านั้น

DBCC SHOW_STATISTICS
    (
        'Production.TransactionHistory', 
        'stats Production.TransactionHistory TransactionDate TransactionID'
    );

สถิติหลายคอลัมน์

ด้วยสถิติหลายคอลัมน์เหล่านี้ในสถานที่ ...

SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

... แผนการดำเนินการแสดงการประมาณการที่เหมือนกับเมื่อมีสถิติคอลัมน์เดียวเท่านั้นที่มีอยู่:

แผนสถิติหลายคอลัมน์

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