ทำสถิติการอัพเดตดัชนีใหม่หรือไม่?


43

ฉันได้ทำหลักสูตร MS10775A เมื่อสัปดาห์ที่แล้วและมีคำถามหนึ่งข้อที่ผู้ฝึกสอนไม่สามารถตอบได้อย่างน่าเชื่อถือคือ:

ดัชนีใหม่อัปเดตสถิติหรือไม่

เราพบว่าการสนทนาออนไลน์โต้เถียงทั้งที่เป็นอยู่และไม่เป็นเช่นนั้น


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

คำตอบ:


51

คุณสามารถระลึกถึงสิ่งต่อไปนี้ได้เมื่อใส่ใจเกี่ยวกับการอัปเดตสถิติ (คัดลอกจากดัชนีการสร้างใหม่กับการอัปเดตสถิติ (Benjamin Nevarez)

  1. โดยค่าเริ่มต้นUPDATE STATISTICSคำสั่งใช้เพียงตัวอย่างของบันทึกของตาราง การใช้UPDATE STATISTICS WITH FULLSCANจะสแกนทั้งตาราง

  2. โดยค่าเริ่มต้นUPDATE STATISTICSคำสั่งปรับปรุงสถิติดัชนีและคอลัมน์ การใช้COLUMNSตัวเลือกจะอัปเดตสถิติคอลัมน์เท่านั้น การใช้INDEXตัวเลือกจะอัปเดตสถิติดัชนีเท่านั้น

  3. การสร้างดัชนีใหม่ตัวอย่างเช่นโดยใช้ALTER INDEX … REBUILDจะอัปเดตสถิติดัชนีด้วยการใช้งานที่เทียบเท่าWITH FULLSCAN ยกเว้นว่า ตารางถูกแบ่งพาร์ติชันซึ่งในกรณีนี้สถิติจะถูกสุ่มตัวอย่างเท่านั้น (ใช้กับ SQL Server 2012 และใหม่กว่า)

  4. สถิติที่ถูกสร้างขึ้นด้วยตนเองโดยใช้CREATE STATISTICSจะไม่มีการปรับปรุงใด ๆการดำเนินงานรวมทั้ง ALTER INDEX ... REBUILD อัปเดตสถิติสำหรับดัชนีคลัสเตอร์หากมีการกำหนดไว้ในตารางที่สร้างใหม่ALTER TABLE ... REBUILDALTER TABLE ... REBUILD

  5. การจัดระเบียบดัชนีใหม่ตัวอย่างเช่นการใช้ALTER INDEX … REORGANIZEไม่ได้อัพเดตสถิติใด ๆ

คำตอบสั้น ๆ คือคุณต้องใช้UPDATE STATISTICSเพื่ออัปเดตสถิติคอลัมน์และการสร้างดัชนีใหม่จะอัปเดตสถิติดัชนีเท่านั้น คุณสามารถบังคับให้อัปเดตสถิติทั้งหมดบนตารางรวมถึง index-stats และสถิติที่สร้างขึ้นด้วยตนเองด้วยUPDATE STATISTICS (tablename) WITH FULLSCAN;ไวยากรณ์

รหัสต่อไปนี้แสดงกฎที่สรุปด้านบน:

ก่อนอื่นเราจะสร้างตารางที่มีคอลัมน์สองคอลัมน์และดัชนีแบบกลุ่ม:

USE tempdb;

IF OBJECT_ID(N'dbo.SomeTable', N'U') IS NOT NULL
DROP TABLE dbo.SomeTable;

CREATE TABLE dbo.SomeTable
(
    rn int NOT NULL IDENTITY(1,1)
        CONSTRAINT pk
        PRIMARY KEY NONCLUSTERED
    , i int NOT NULL INDEX i 
    , d sysname NOT NULL
) ON [PRIMARY] WITH (DATA_COMPRESSION = NONE);

CREATE UNIQUE CLUSTERED INDEX cx ON dbo.SomeTable (i, d);

CREATE STATISTICS d ON dbo.SomeTable (d) WITH FULLSCAN;

INSERT INTO dbo.SomeTable (d, i)
SELECT c1.name, c1.id
FROM sys.syscolumns c1;

เคียวรีนี้แสดงวันที่ที่แต่ละอ็อบเจ็กต์สถานะถูกอัพเดตล่าสุด:

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';

ผลลัพธ์แสดงว่าไม่มีการอัปเดตเกิดขึ้นซึ่งถูกต้องตั้งแต่เราเพิ่งสร้างตาราง:

╔═══════════════╦═══════════╦═══════════╗
║ ObjectName ║ StatsName ║ StatsDate ║
╠═══════════════╬═══════════╬═══════════╣
║ dbo.SomeTable ║ cx ║ NULL ║
║ dbo.SomeTable ║ i ║ NULL ║
║ dbo.SomeTable ║ pk ║ NULL ║
║ dbo.SomeTable ║ d ║ NULL ║
╚═══════════════╩═══════════╩═══════════╝

มาสร้างตารางทั้งหมดกันใหม่และดูว่าการอัปเดตสถิตินั้นหรือไม่:

ALTER TABLE dbo.SomeTable REBUILD;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗
║ ObjectName ║ StatsName ║ StatsDate ║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.590 ║
║ dbo.SomeTable ║ i ║ NULL ║
║ dbo.SomeTable ║ pk ║ NULL ║
║ dbo.SomeTable ║ d ║ NULL ║
╚═══════════════╩═══════════╩═════════════════════ ════╝

ผลลัพธ์แสดงเฉพาะสถิติดัชนีคลัสเตอร์ที่ถูกอัพเดต

ต่อไปเราทำการแยกแบบUPDATE STATS:

UPDATE STATISTICS dbo.SomeTable(d) WITH FULLSCAN;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';

อย่างที่คุณเห็นเราเพิ่งอัปเดตสถิติในdคอลัมน์:

╔═══════════════╦═══════════╦═════════════════════ ════╗
║ ObjectName ║ StatsName ║ StatsDate ║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.590 ║
║ dbo.SomeTable ║ i ║ NULL ║
║ dbo.SomeTable ║ pk ║ NULL ║
║ dbo.SomeTable ║ d ║ 2018-09-17 14: 09: 13.597 ║
╚═══════════════╩═══════════╩═════════════════════ ════╝

ตอนนี้เราจะอัปเดตสถิติในตารางทั้งหมด:

UPDATE STATISTICS dbo.SomeTable WITH FULLSCAN;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗
║ ObjectName ║ StatsName ║ StatsDate ║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.600 ║
║ dbo.SomeTable ║ i ║ 2018-09-17 14: 09: 13.600 ║
║ dbo.SomeTable ║ pk ║ 2018-09-17 14: 09: 13.603 ║
║ dbo.SomeTable ║ d ║ 2018-09-17 14: 09: 13.607 ║
╚═══════════════╩═══════════╩═════════════════════ ════╝

UPDATE STATISTICS (table);ในขณะที่คุณสามารถดูวิธีเดียวที่จะให้แน่ใจสถิติทั้งหมดที่มีการปรับปรุงคือการปรับปรุงอย่างใดอย่างหนึ่งแต่ละคนด้วยตนเองหรือการปรับปรุงตารางทั้งหมดที่มี


@JeremyWeir - ในขณะที่คุณสามารถดูจากรหัสตัวอย่างฉันเพิ่งเพิ่มคำถามข้างต้นสถิติเพียงการปรับปรุงเป็นผู้ที่มีการปรับปรุงอย่างชัดเจนทั้งผ่านการอย่างใดอย่างหนึ่งALTER INDEX ... REBUILDหรือUPDATE STATISTICSคำสั่ง หากตารางถูกสร้างขึ้นใหม่สถิติดัชนีคลัสเตอร์เท่านั้นที่จะถูกอัพเดต FYI คีย์หลักและดัชนีคลัสเตอร์ไม่จำเป็นต้องได้รับการสนับสนุนโดยวัตถุดัชนีเดียวกัน
Max Vernon

5

หน้า Microsoft เอกสารสำหรับสถานะสถิติของ SQL Server :

การดำเนินการเช่นการสร้างใหม่การจัดเรียงข้อมูลหรือจัดโครงสร้างดัชนีใหม่จะไม่เปลี่ยนแปลงการกระจายข้อมูล ดังนั้นคุณไม่จำเป็นต้องปรับปรุงสถิติหลังจากดำเนินการแก้ไข rebuild ดัชนี DBCC DBREINDEX, DBCC INDEXDEFRAG หรือการดำเนินการจัดระเบียบ เครื่องมือเพิ่มประสิทธิภาพ Query จะอัปเดตสถิติเมื่อคุณสร้างดัชนีใหม่บนตารางหรือมุมมองด้วย ALTER INDEX REBUILD หรือ DBCC DBREINDEX อย่างไรก็ตามการอัพเดตสถิตินี้เป็นผลพลอยได้จากการสร้างดัชนีใหม่ เครื่องมือเพิ่มประสิทธิภาพแบบสอบถามไม่อัปเดตสถิติหลังการดำเนินการ DBCC INDEXDEFRAG หรือ ALTER INDEX REORGANIZE

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