ฉันได้ทำหลักสูตร MS10775A เมื่อสัปดาห์ที่แล้วและมีคำถามหนึ่งข้อที่ผู้ฝึกสอนไม่สามารถตอบได้อย่างน่าเชื่อถือคือ:
ดัชนีใหม่อัปเดตสถิติหรือไม่
เราพบว่าการสนทนาออนไลน์โต้เถียงทั้งที่เป็นอยู่และไม่เป็นเช่นนั้น
ฉันได้ทำหลักสูตร MS10775A เมื่อสัปดาห์ที่แล้วและมีคำถามหนึ่งข้อที่ผู้ฝึกสอนไม่สามารถตอบได้อย่างน่าเชื่อถือคือ:
ดัชนีใหม่อัปเดตสถิติหรือไม่
เราพบว่าการสนทนาออนไลน์โต้เถียงทั้งที่เป็นอยู่และไม่เป็นเช่นนั้น
คำตอบ:
คุณสามารถระลึกถึงสิ่งต่อไปนี้ได้เมื่อใส่ใจเกี่ยวกับการอัปเดตสถิติ (คัดลอกจากดัชนีการสร้างใหม่กับการอัปเดตสถิติ (Benjamin Nevarez)
โดยค่าเริ่มต้นUPDATE STATISTICS
คำสั่งใช้เพียงตัวอย่างของบันทึกของตาราง การใช้UPDATE STATISTICS WITH FULLSCAN
จะสแกนทั้งตาราง
โดยค่าเริ่มต้นUPDATE STATISTICS
คำสั่งปรับปรุงสถิติดัชนีและคอลัมน์ การใช้COLUMNS
ตัวเลือกจะอัปเดตสถิติคอลัมน์เท่านั้น การใช้INDEX
ตัวเลือกจะอัปเดตสถิติดัชนีเท่านั้น
การสร้างดัชนีใหม่ตัวอย่างเช่นโดยใช้ALTER INDEX … REBUILD
จะอัปเดตสถิติดัชนีด้วยการใช้งานที่เทียบเท่าWITH FULLSCAN
ยกเว้นว่า ตารางถูกแบ่งพาร์ติชันซึ่งในกรณีนี้สถิติจะถูกสุ่มตัวอย่างเท่านั้น (ใช้กับ SQL Server 2012 และใหม่กว่า)
สถิติที่ถูกสร้างขึ้นด้วยตนเองโดยใช้CREATE STATISTICS
จะไม่มีการปรับปรุงใด ๆการดำเนินงานรวมทั้ง ALTER INDEX ... REBUILD
อัปเดตสถิติสำหรับดัชนีคลัสเตอร์หากมีการกำหนดไว้ในตารางที่สร้างใหม่ALTER TABLE ... REBUILD
ALTER TABLE ... REBUILD
การจัดระเบียบดัชนีใหม่ตัวอย่างเช่นการใช้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);
ในขณะที่คุณสามารถดูวิธีเดียวที่จะให้แน่ใจสถิติทั้งหมดที่มีการปรับปรุงคือการปรับปรุงอย่างใดอย่างหนึ่งแต่ละคนด้วยตนเองหรือการปรับปรุงตารางทั้งหมดที่มี
ALTER INDEX ... REBUILD
หรือUPDATE STATISTICS
คำสั่ง หากตารางถูกสร้างขึ้นใหม่สถิติดัชนีคลัสเตอร์เท่านั้นที่จะถูกอัพเดต FYI คีย์หลักและดัชนีคลัสเตอร์ไม่จำเป็นต้องได้รับการสนับสนุนโดยวัตถุดัชนีเดียวกัน
หน้า Microsoft เอกสารสำหรับสถานะสถิติของ SQL Server :
การดำเนินการเช่นการสร้างใหม่การจัดเรียงข้อมูลหรือจัดโครงสร้างดัชนีใหม่จะไม่เปลี่ยนแปลงการกระจายข้อมูล ดังนั้นคุณไม่จำเป็นต้องปรับปรุงสถิติหลังจากดำเนินการแก้ไข rebuild ดัชนี DBCC DBREINDEX, DBCC INDEXDEFRAG หรือการดำเนินการจัดระเบียบ เครื่องมือเพิ่มประสิทธิภาพ Query จะอัปเดตสถิติเมื่อคุณสร้างดัชนีใหม่บนตารางหรือมุมมองด้วย ALTER INDEX REBUILD หรือ DBCC DBREINDEX อย่างไรก็ตามการอัพเดตสถิตินี้เป็นผลพลอยได้จากการสร้างดัชนีใหม่ เครื่องมือเพิ่มประสิทธิภาพแบบสอบถามไม่อัปเดตสถิติหลังการดำเนินการ DBCC INDEXDEFRAG หรือ ALTER INDEX REORGANIZE
REINDEX
อัปเดตสถิติคอลัมน์เป็นผลข้างเคียงของการสร้างดัชนีใหม่ - คุณไม่จำเป็นต้องอัปเดตสถิติ ข้อมูลในตารางไม่เปลี่ยนแปลง มันเป็นข้อมูลเดียวกันมีเพียง a) ย้ายตำแหน่งของมันบนจานหมุน (เมื่อจัดหน้าใหม่) หรือ b) นั่งในหน้าอื่น (ในกรณีที่สร้างใหม่) ดังนั้น: ดัชนีใหม่จะอัปเดตสถิติ (บางส่วน): ไม่จำเป็นต้องทำ