การค้นหาและการอัปเดตช้ามากหลังจากดัชนีเพิ่มประสิทธิภาพ


12

ฐานข้อมูล SQL Server 2017 Enterprise CU16 14.0.3076.1

เราเพิ่งพยายามเปลี่ยนจากดัชนีเริ่มต้นสร้างงานบำรุงรักษาไป Ola IndexOptimizeHallengren งานสร้างดัชนีเริ่มต้นใหม่ทำงานเป็นเวลาสองสามเดือนโดยไม่มีปัญหาใด ๆ และแบบสอบถามและการปรับปรุงกำลังทำงานด้วยเวลาดำเนินการที่ยอมรับได้ หลังจากทำงานIndexOptimizeบนฐานข้อมูล:

EXECUTE dbo.IndexOptimize
@Databases = 'USER_DATABASES',
@FragmentationLow = NULL,
@FragmentationMedium = 'INDEX_REORGANIZE,INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',
@FragmentationHigh = 'INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',
@FragmentationLevel1 = 5,
@FragmentationLevel2 = 30,
@UpdateStatistics = 'ALL',
@OnlyModifiedStatistics = 'Y'

ประสิทธิภาพลดลงอย่างมาก คำสั่งการปรับปรุงที่ใช้เวลา 100 มิลลิวินาทีก่อนที่จะIndexOptimizeใช้เวลา 78.000ms หลังจากนั้น (โดยใช้แผนเหมือนกัน) และข้อความค้นหาก็มีประสิทธิภาพที่แย่กว่านั้นอีกหลายคำสั่ง

เนื่องจากสิ่งนี้ยังคงเป็นฐานข้อมูลทดสอบ (เรากำลังย้ายระบบการผลิตจาก Oracle) เราจึงเปลี่ยนกลับเป็นข้อมูลสำรองและปิดการใช้งานIndexOptimizeและทุกสิ่งกลับสู่ปกติ

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

แผนการดำเนินการสำหรับคำสั่งการปรับปรุงเมื่อมันช้า เช่น
หลังจาก IndexOptimize
แผนการดำเนินการจริง (มาโดยเร็ว)

ฉันไม่สามารถแยกความแตกต่างได้
วางแผนสำหรับการค้นหาเดียวกันเมื่อวางแผนการดำเนินการจริงที่รวดเร็ว

คำตอบ:


11

ฉันสงสัยว่าคุณมีอัตราตัวอย่างที่แตกต่างกันระหว่างสองวิธีการบำรุงรักษาของคุณ ฉันเชื่อว่าสคริปต์ของ Ola ใช้การสุ่มตัวอย่างเริ่มต้นเว้นแต่คุณจะระบุ@StatisticsSampleพารามิเตอร์ซึ่งดูเหมือนว่าคุณกำลังทำอยู่

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

SELECT  OBJECT_SCHEMA_NAME(st.object_id) + '.' + OBJECT_NAME(st.object_id) AS TableName
    ,   col.name AS ColumnName
    ,   st.name AS StatsName
    ,   sp.last_updated
    ,   sp.rows_sampled
    ,   sp.rows
    ,   (1.0*sp.rows_sampled)/(1.0*sp.rows) AS sample_pct
FROM sys.stats st 
    INNER JOIN sys.stats_columns st_col
        ON st.object_id = st_col.object_id
        AND st.stats_id = st_col.stats_id
    INNER JOIN sys.columns col
        ON st_col.object_id = col.object_id
        AND st_col.column_id = col.column_id
    CROSS APPLY sys.dm_db_stats_properties (st.object_id, st.stats_id) sp
ORDER BY 1, 2

หากคุณเห็นว่าสิ่งนี้กำลังผ่าน 1s (เช่น 100%) โอกาสนี่เป็นปัญหาของคุณ อาจลองใช้สคริปต์ของ Ola อีกครั้งรวมถึง@StatisticsSampleพารามิเตอร์ด้วยเปอร์เซ็นต์ที่ได้รับจากการสืบค้นนี้และดูว่าสิ่งนั้นช่วยแก้ปัญหาของคุณหรือไม่


เป็นหลักฐานสนับสนุนเพิ่มเติมสำหรับทฤษฎีนี้ XML แผนการดำเนินการแสดงอัตราการสุ่มตัวอย่างที่แตกต่างกันอย่างมากสำหรับการสืบค้นที่ช้า (2.18233%):

<StatisticsInfo LastUpdate="2019-09-01T01:07:46.04" ModificationCount="0" 
    SamplingPercent="2.18233" Statistics="[INDX_UPP_4]" Table="[UPPDRAG]" 
    Schema="[SVALA]" Database="[ulek-sva]" />

เมื่อเปรียบเทียบกับการสืบค้นที่รวดเร็ว (100%):

<StatisticsInfo LastUpdate="2019-08-25T23:01:05.52" ModificationCount="555" 
    SamplingPercent="100" Statistics="[INDX_UPP_4]" Table="[UPPDRAG]" 
    Schema="[SVALA]" Database="[ulek-sva]" />

@JoshDarnell LOL นี่เป็นเหตุการณ์ที่เกิดขึ้นครั้งที่สองที่คุณพบข้อมูลสถิติสนับสนุนบางอย่างในแผนแบบสอบถามที่ฉันไม่เห็น ขอบคุณสำหรับการแก้ไข!
John Eisbrener

ฮ่าฮ่าฉันลืมไปแล้วนั่นคือคุณจอห์น! ฉันสัญญาว่าฉันจะไม่สะกดรอยตามคุณ😅
Josh Darnell

@JoshDarnell ฉันขอขอบคุณข้อมูลเชิงลึกเพิ่มเติมและเป็นอีกหนึ่งการแจ้งเตือนที่ดีว่ามีข้อมูลมากมายในแผนการดำเนินการที่คุณไม่ควรข้าม
John Eisbrener

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

ขอบคุณสำหรับคำอธิบายนี้มันเป็นปัญหาแน่นอน สถิติส่วนใหญ่มีอัตราตัวอย่างเริ่มต้นที่ 2.2% แต่ไม่กี่รายการที่สร้างขึ้นหลังจากการโยกย้ายจาก Oracle มีอัตราตัวอย่าง 100% ดูเหมือนว่าการสร้างดัชนีเริ่มต้นจะเก็บไว้ 100% แต่เมื่อเราใช้ IndexOptimize ก็จะใช้ค่าเริ่มต้นที่ 2.2% กับดัชนีเหล่านั้นเช่นกัน การใช้พารามิเตอร์ @StatisticsSample และเรียกใช้คิวรีอีกครั้งยืนยันว่านี่คือสิ่งที่ทำให้เกิดปัญหา
Martin Bergström

5

คำตอบของ John เป็นคำตอบที่ถูกต้องนี่เป็นเพียงส่วนเสริมของแผนการดำเนินการที่เปลี่ยนไปและเป็นตัวอย่างเกี่ยวกับวิธีการสังเกตเห็นความแตกต่างได้อย่างง่ายดายด้วยSentry One Plan explorer

คำแถลงการปรับปรุงที่ใช้เวลา 100ms ก่อนที่ IndexOptimize จะใช้เวลา 78.000ms หลังจากนั้น (ใช้แผนเหมือนกัน)

เมื่อดูแผนแบบสอบถามทั้งหมดเมื่อประสิทธิภาพของคุณลดลงคุณสามารถสังเกตเห็นความแตกต่างได้อย่างง่ายดาย

ประสิทธิภาพลดลง

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

สองครั้งนับจากเวลา CPU มากกว่า 35 วินาทีและเวลาที่ผ่านไป

ประสิทธิภาพที่คาดหวัง

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

ดีกว่ามาก

การย่อยสลายหลักคือสองครั้งในแบบสอบถามแบบใช้ปรับปรุงนี้:

UPDATE SVALA.INGÅENDEANALYS
                           SET 
                              UPPDRAGAVSLUTAT = @NEW$AVSLUTAT
                        WHERE INGÅENDEANALYS.ID IN 
                           (
                              SELECT IA.ID
                              FROM 
                                 SVALA.INGÅENDEANALYS  AS IA 
                                    JOIN SVALA.INGÅENDEANALYSX  AS IAX 
                                    ON IAX.INGÅENDEANALYS = IA.ID 
                                    JOIN SVALA.ANALYSMATERIAL  AS AM 
                                    ON AM.ID = IA.ANALYSMATERIALID 
                                    JOIN SVALA.ANALYSMATERIALX  AS AMX 
                                    ON AMX.ANALYSMATERIAL = AM.ID 
                                    JOIN SVALA.INSÄNTMATERIAL  AS IM 
                                    ON IM.ID = AM.INSÄNTMATERIALID 
                                    JOIN SVALA.INSÄNTMATERIALX  AS IMX 
                                    ON IMX.INSÄNTMATERIAL = IM.ID
                              WHERE IM.UPPDRAGSID = SVALA.PKGSVALA$STRIPVERSION(@NEW$ID)
                      )

แผนการดำเนินการสำหรับแบบสอบถามนี้ด้วยประสิทธิภาพที่ลดลง

แผนแบบสอบถามโดยประมาณของแบบสอบถามแบบใช้ปรับปรุงนี้มีการประเมินที่สูงมากเมื่อประสิทธิภาพลดลง:

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

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

ผลกระทบที่ใหญ่ที่สุดต่อประสิทธิภาพคือการสแกนและแฮชสองรายการเข้าร่วมด้านล่าง:

การสแกนที่แท้จริงเกี่ยวกับประสิทธิภาพที่ลดลง # 1

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

การสแกนที่แท้จริงเกี่ยวกับประสิทธิภาพที่ลดลง # 2

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


แผนการดำเนินการสำหรับแบบสอบถามนี้ด้วยประสิทธิภาพที่คาดหวัง

เมื่อคุณเปรียบเทียบกับค่าประมาณ (หรือค่าจริง) ของแผนคิวรีที่มีประสิทธิภาพตามที่คาดหวังความแตกต่างนั้นง่ายที่จะมองเห็น

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

นอกจากนี้การเข้าถึงสองตารางก่อนหน้านี้ไม่ได้เกิดขึ้นด้วย:

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

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

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

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


1
ขอบคุณสำหรับคำอธิบายรายละเอียดของแผนมันเป็นประโยชน์อย่างมากกับความเข้าใจของฉันว่าทำไมปัญหาเกิดขึ้น ฉันจะดู Sentry One Plan Explorer แน่นอนมันมีประโยชน์มาก!
Martin Bergström

@ MartinBergströmเป็นเรื่องที่ดีมากที่ได้ยินขอขอบคุณสำหรับการจัดทำแผนแบบสอบถามและให้ข้อมูลที่เกี่ยวข้องทั้งหมดที่เราถามถึงในความคิดเห็น :) สิ่งที่ดีที่สุดเกี่ยวกับแผนสำรวจคือมันฟรี! นอกจากนี้ยังสามารถทำงานได้จากภายใน ssms (โดยการคลิกขวาที่แผนปฏิบัติการและกด "ดูด้วย sentryone plan explorer")
Randi Vertongen

1

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

สองคะแนนง่ายมากจากไม้ตีแม้ว่า:

  1. การเพิ่มประสิทธิภาพทำงานเสร็จสมบูรณ์อย่างแน่นอนหรือไม่? หากการทดสอบของคุณกำลังแข่งขันกับ IO ของการสร้างดัชนีที่ใช้เวลานานซึ่งจะส่งผลต่อการกำหนดเวลา
  2. คุณทดสอบหลาย ๆ ครั้งหรือไม่ หากการอัปเดตอิงจากข้อมูลจากแบบสอบถามที่พิจารณาข้อมูลจำนวนมาก (แทนที่จะเป็น `UPDATE แบบง่าย TheTable SET ThisColumn = 'ค่าคงที่') อาจเป็นไปได้ว่าข้อมูลนี้เป็นปกติในหน่วยความจำ แต่ถูกล้างออกใน ซึ่งการรันครั้งแรกของคิวรีที่เกี่ยวข้องจะช้ากว่าปกติเนื่องจากการกดปุ่มดิสก์มากกว่าการค้นหาหน้าที่ต้องการในบัฟเฟอร์พูลในหน่วยความจำ

ขอบคุณที่สละเวลาตอบ ฉันได้อัปเดตคำถามด้วยลิงก์ pastetheplan แล้ว การเพิ่มประสิทธิภาพเสร็จสมบูรณ์อย่างแน่นอนมันวิ่งประมาณ 1 ชั่วโมงวันก่อนที่ปัญหาจะเกิดขึ้น เราทำการทดสอบหลายครั้งและจริง ๆ แล้วมันมีผลต่อฐานข้อมูลสองชุดที่ทำงานในสภาพแวดล้อมการทดสอบที่แตกต่างกันสองแบบในลักษณะเดียวกัน คำสั่ง Update เป็นเพียงตัวอย่างที่ง่ายที่สุดที่ฉันพบมีเม็ดมีดอื่น ๆ อีกมากมายและเลือกรับผลกระทบ
Martin Bergström

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

ขออภัยถ้าคำตอบของฉันไม่ชัดเจน ใช่เราลองอัปเดตหลายครั้ง การชะลอตัวเกิดขึ้นบนฐานข้อมูลที่ผู้ทดสอบใช้เพื่อทดสอบแอปพลิเคชันและแบบสอบถามและอัปเดตที่ทำงานหลายครั้งในระหว่างวันโดยไม่มีการปรับปรุงประสิทธิภาพ
Martin Bergström
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.