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


22

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

1 , 2 , 3 , 4

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

อย่างไรก็ตามถ้าฉันกรองส่วนอื่น ๆ ของมิติตัวเพิ่มประสิทธิภาพจะค้นหา PK / CI ของแต่ละตารางพื้นฐาน

นี่คือคำถามที่ถาม:

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where o.ObservationDateKey >= 20000101
    and o.ObservationDateKey <= 20051231
group by od.[Year];

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where od.DateKey >= 20000101
    and od.DateKey <= 20051231
group by od.[Year];

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where od.[Year] >= 2000 and od.[Year] < 2006
group by od.[Year];

ตัวกรองข้อเท็จจริงบนคีย์

ตัวกรองสลัวที่สำคัญ

ตัวกรองสลัวในแง่มุม

นี่คือลิงค์ไปยังเซสชัน SQL Sentry Plan Explorer

ฉันกำลังทำการแบ่งพาร์ติชันตารางที่ใหญ่กว่าจริง ๆ เพื่อดูว่าฉันได้รับการแบ่งพาร์ติชันเพื่อตอบสนองในลักษณะเดียวกันหรือไม่

ฉันจะได้รับการกำจัดพาร์ทิชันสำหรับแบบสอบถาม (ง่าย) ที่กรองในด้านของมิติ

ในระหว่างนี้นี่เป็นสำเนาของฐานข้อมูลเท่านั้น:

https://gist.github.com/swasheck/9a22bf8a580995d3b2aa

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

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

เวอร์ชันเซิร์ฟเวอร์ SQL:

Microsoft SQL Server 2014 - 12.0.2000.8 (X64) 
    Feb 20 2014 20:04:26 
    Copyright (c) Microsoft Corporation
    Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)

เพียงแค่ FYI .. สตรีมสถิติล่าสุดเสียหายCREATE STATISTICS [_WA_Sys_00000008_2FCF1A8A] ON [dbo].[Observation_2010]([StationStateCode]) WITH STATS_STREAM = 0x01000000010000000000000000000000D4531EDB00000000D5080000000000009508000000000000AF030000AF000000020000000000000008D000340000000007000000E65DE0007DA5000076F9780000000000867704000000000000000000ABAAAA3C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Kin Shah

ดูเหมือนว่าสคริปต์สำหรับฐานข้อมูลสถิติอย่างเดียวจะถูกตัดทอน ฉันพยายามคลิก "ดูไฟล์ทั้งหมด" และดาวน์โหลด zip แต่ไม่ว่าจะด้วยวิธีใดฉันก็ไม่มีสถิติสำหรับObservationDatesตาราง ฉันไม่ได้รับแผนเดียวกับ Paul แม้แต่กับ 4199 และฉันคิดว่านี่เป็นเหตุผล
Geoff Patterson

@GeoffPatterson มันใช้งานได้สำหรับฉัน คุณคลิกลิงก์ไปยังไฟล์ raw หรือไม่ gist.githubusercontent.com/swasheck/9a22bf8a580995d3b2aa/raw/ … อย่างไรก็ตามตามที่ Kin ตั้งข้อสังเกตกระแสสถิติล่าสุดเสียหาย: /
swasheck

ฉันคลิกลิงก์สำหรับไฟล์ raw สคริปต์ที่ทำงาน (ยกเว้นปัญหา Kin ระบุไว้) แต่ไม่ได้มีตรรกะใด ๆ ObservationDatesที่จะสร้างสถิติเกี่ยวกับ ฉันลงเอยUPDATE STATISTICS ObservationDates WITH ROWCOUNT = 10000ด้วยตนเองเพื่อให้ได้แผนที่ Paul แสดงให้เห็น
Geoff Patterson

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

คำตอบ:


10

เปิดใช้งานการตั้งค่าสถานะการติดตาม 4199

ฉันยังต้องออก:

UPDATE STATISTICS dbo.ObservationDates 
WITH ROWCOUNT = 73049;

เพื่อรับแผนที่แสดงด้านล่าง สถิติสำหรับตารางนี้หายไปจากการอัปโหลด ตัวเลข 73,049 มาจากข้อมูล Table Cardinality ในไฟล์แนบ Plan Explorer ฉันใช้ SQL Server 2014 SP1 CU4 (สร้าง 12.0.4436) พร้อมตัวประมวลผลเชิงตรรกะสองตัวหน่วยความจำสูงสุดตั้งไว้ที่ 2048 MB และไม่มีการตั้งค่าสถานะการติดตามนอกเหนือจาก 4199

คุณควรได้รับแผนการดำเนินการที่มีการกำจัดพาร์ติชันแบบไดนามิก:

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where 
    od.[Year] >= 2000 and od.[Year] < 2006
group by 
    od.[Year]
option (querytraceon 4199);

ส่วนย่อยของแผน:

ส่วนย่อยของแผน

นี้อาจจะดูแย่ลง แต่ตัวกรองที่มีทั้งหมดเริ่มต้นขึ้นฟิลเตอร์ ตัวอย่างคำกริยาคือ:

คุณสมบัติตัวกรอง

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

นี่อาจจะไม่ค่อยมีประสิทธิภาพเท่ากับการกำจัดไฟฟ้าสถิตโดยเฉพาะอย่างยิ่งหากแผนขนาน

คุณอาจจะต้องลองคำแนะนำเช่นMAXDOP 1, FAST 1หรือFORCESEEKในมุมมองที่จะได้รับแผนเดียวกัน ตัวเลือกการคิดต้นทุนของเครื่องมือเพิ่มประสิทธิภาพพร้อมมุมมองที่แบ่งพาร์ติชัน (เช่นตารางที่แบ่งพาร์ติชัน) อาจเป็นเรื่องยุ่งยาก

ประเด็นคือคุณต้องมีแผนที่มีตัวกรองเริ่มต้นขึ้นเพื่อรับการกำจัดพาร์ติชันแบบไดนามิกพร้อมมุมมองที่แบ่งพาร์ติชัน


ข้อความค้นหาที่มีUSE PLANคำแนะนำในตัว: (ผ่าน gist.github.com):


1
ข้อมูลที่ดีขอบคุณ Paul! ฉันสงสัยว่าหลังจากที่ฉันเขียนคำตอบแล้วทำไม SQL Server ถึงไม่มีวิธีกำจัดแบบนี้ ปรากฎว่ามีฉันเพิ่งไม่เคยเห็นมาก่อน!
Geoff Patterson

6

การสังเกตของฉันได้เสมอว่าคุณต้องระบุค่า (หรือช่วงของค่า) สำหรับคอลัมน์พาร์ติชันอย่างชัดเจนในแบบสอบถามเพื่อรับ "การกำจัดตาราง" ในมุมมองพาร์ติชัน สิ่งนี้อิงจากประสบการณ์การใช้มุมมองที่แบ่งพาร์ติชันในการผลิตจาก SQL Server 2000 ถึง SQL Server 2014

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

โปรดทราบว่าสำหรับตารางที่แบ่งพาร์ติชันแล้วระบบจะสนับสนุนการค้นหาประเภทนี้ (ไปยังพาร์ติชันเฉพาะ)

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

-- Gather than the min/max values for the partition column
DECLARE @minDateKey INT,
        @maxDateKey INT
SELECT @minDateKey = MIN(DateKey),
        @maxDateKey = MAX(DateKey)
FROM dbo.ObservationDates od
WHERE od.[Year] >= 2000 and od.[Year] < 2006

-- Since I have a stats-only copy of the database, simulate having run the query above
-- (You can comment this out since you have the actual data.)
SELECT @minDateKey = 20000101, @maxDateKey = 20051231

-- Adjust the query to use the min/max values of the partition column
-- rather than filtering on a different column in the dimension table
select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
WHERE od.DateKey >= @minDateKey AND od.DateKey <= @maxDateKey
group by od.[Year]
-- Must use OPTION RECOMPILE; otherwise the plan will touch all tables because it
-- must do so in order to be valid for all values of the parameters!
OPTION (RECOMPILE)

นี่เป็นแผนต่อไปนี้ ขณะนี้มีคิวรีพิเศษที่กระทบกับตารางมิติ แต่คิวรีเหนือตารางข้อเท็จจริง (น่าจะใหญ่กว่ามาก) จะได้รับการปรับให้เหมาะสม

ป้อนคำอธิบายรูปภาพที่นี่


จะได้ผลเช่นเดียวกันหรือไม่หากคุณรวมการสืบค้นแรกเข้าในการสืบค้นที่สองโดยไม่ต้องใช้การไล่ล่าของตัวแปร
Andriy M

@AndriyM ถ้าฉันเข้าใจคุณถูกต้องคำตอบคือไม่ผลเช่นเดียวกันจะไม่เกิดขึ้นและแผนแบบสอบถามจะแตะทุกตารางในมุมมองที่แบ่งพาร์ติชันหากคุณพยายามรวมสองแบบสอบถาม หากคุณต้องดำเนินการแบบสอบถามแรกให้วางค่า20000101และ20051231แทนตัวแปร (หรือทำสิ่งที่คล้ายกันผ่านแบบสอบถามที่แยกกันสองรายการในแอปพลิเคชันของคุณ) แล้วใช่ผลที่ได้จะเหมือนกันโดยไม่ต้องใช้ตัวแปร
Geoff Patterson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.