Yeniden endeksleme istatistikleri günceller mi?


43

Geçtiğimiz hafta MS10775A kursunu yapıyorum ve eğitimcinin güvenilir şekilde cevaplayamadığı bir soru:

Yeniden indeks istatistikleri günceller mi?

Hem yaptığını hem de yapmadığını savunarak tartışmalar yaptık.


Bir REINDEXsütununun, dizini yeniden oluşturmanın bir yan etkisi olarak güncellediğini unutmayın; istatistikleri güncellemeniz gerekmez . Tablodaki veriler değişmez. Aynı veridir, sadece a) döndürme tablasındaki yerini (sayfa yeniden düzenlendiğinde) veya b) farklı bir sayfada otururken (yeniden yapılanma durumunda). Yani: Yeniden endeksi yapar güncelleme (bazı) istatistikleri: hayır yok gerek bunu yapmak için.
Ian Boyd

Yanıtlar:


51

Güncelleme istatistiklerini dikkate alırken aşağıdakileri aklınızda tutabilirsiniz ( İstatistikleri Yeniden Oluşturma ve Güncelleme İstatistikleri (Benjamin Nevarez)

  1. Varsayılan olarak, UPDATE STATISTICSifade tablonun yalnızca bir kayıt örneklerini kullanır. Kullanarak UPDATE STATISTICS WITH FULLSCANtüm tabloyu tarar.

  2. Varsayılan olarak, UPDATE STATISTICSifade hem dizin hem de sütun istatistiklerini günceller. Bu COLUMNSseçeneği kullanmak yalnızca sütun istatistiklerini güncelleyecektir. Bu INDEXseçeneği kullanmak sadece endeks istatistiklerini güncelleyecektir.

  3. Bir dizin yeniden oluşturma kullanılarak örneğin ALTER INDEX … REBUILDkullanarak da eşdeğer olan endeks istatistiklerini güncelleyecektir WITH FULLSCAN sürece istatistikleri yalnızca örneklenir bu durumda, Tablo bölümlere ayrılmışsa (SQL Server 2012 ve daha sonra için geçerlidir).

  4. Kullanılarak elle oluşturulan istatistikler , dahil olmak üzere CREATE STATISTICShiçbir ALTER INDEX ... REBUILDişlem tarafından güncellenmez ALTER TABLE ... REBUILD. ALTER TABLE ... REBUILDYeniden yapılanmakta olan tabloda tanımlanmışsa, kümelenmiş dizin için istatistikleri güncelleştirir.

  5. Bir dizini yeniden düzenlemek , örneğin kullanmak ALTER INDEX … REORGANIZEhiçbir istatistiği güncellemez.

Kısa cevap, UPDATE STATISTICSsütun istatistiklerini güncellemek için kullanmanız gerektiği ve bir dizin yeniden inşasının yalnızca dizin istatistiklerini güncelleyeceğidir. Dizin istatistikleri ve el ile oluşturulan istatistikler de dahil olmak üzere bir tablodaki tüm istatistiklere UPDATE STATISTICS (tablename) WITH FULLSCAN;sözdizimi ile güncellemeyi zorlayabilirsiniz .

Aşağıdaki kod yukarıda belirtilen kuralları göstermektedir:

İlk önce, birkaç sütun ve kümelenmiş bir dizin içeren bir tablo oluşturacağız:

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;

Bu sorgu, her bir istatistik nesnesinin en son güncellendiği tarihi gösterir:

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';

Sonuçlar, henüz bir güncelleme oluşturmadıklarını gösteriyor; bu tabloyu yeni oluşturduğumuzdan beri doğru:

╔═══════════════╦═══════════╦═══════════╗
║ NesneAdı ║ İstatistiklerAdı ║ StatsDate ║
╠═══════════════╬═══════════╬═══════════╣
║ dbo.SomeTable ║ cx ║ NULL ║
║ dbo.SomeTable ║ i ║ NULL ║
║ dbo.SomeTable ║ pk ║ NULL ║
║ dbo.SomeTable ║ d ║ NULL ║
╚═══════════════╩═══════════╩═══════════╝

Tüm tabloyu yeniden oluşturalım ve bunun istatistikleri güncelleyip güncellemediğini görelim:

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';
╔═══════════════╦═══════════╦═════════════════════ ════╗
║ NesneAdı ║ İstatistiklerAdı ║ StatsDate ║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo. Bazı able cx ║ 2018-09-17 14: 09: 13.590 ║
║ dbo.SomeTable ║ i ║ NULL ║
║ dbo.SomeTable ║ pk ║ NULL ║
║ dbo.SomeTable ║ d ║ NULL ║
╚═══════════════╩═══════════╩═════════════════════ ════╝

Sonuçlar sadece kümelenmiş endeks istatistiklerinin güncellendiğini göstermektedir.

Sonra, ayrık bir UPDATE STATSişlem gerçekleştiriyoruz :

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';

Gördüğünüz gibi, dsütundaki istatistikleri güncelledik :

╔═══════════════╦═══════════╦═════════════════════ ════╗
║ NesneAdı ║ İstatistiklerAdı ║ StatsDate ║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo. Bazı able 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 ║
╚═══════════════╩═══════════╩═════════════════════ ════╝

Şimdi, tüm tablodaki istatistikleri güncelleyeceğiz:

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';
╔═══════════════╦═══════════╦═════════════════════ ════╗
║ NesneAdı ║ İstatistiklerAdı ║ StatsDate ║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo. Bazı able 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 ║
╚═══════════════╩═══════════╩═════════════════════ ════╝

Görebildiğiniz gibi, tüm istatistiklerin güncellendiğinden emin olmanın tek yolu ya her birini manuel olarak güncellemek ya da tüm tabloyu güncellemek UPDATE STATISTICS (table);.


@JeremyWeir - Yukarıdaki soruya eklediğim örnek koddan da görebileceğiniz gibi, güncellenmiş olan tek istatistik, açıkça ya ALTER INDEX ... REBUILDda bir UPDATE STATISTICSifade ile açıkça güncellenen verilerdir . Tablonun kendisi yeniden oluşturulmuşsa, yalnızca kümelenmiş dizin istatistikleri güncellenir. FYI, bir birincil anahtar ve kümelenmiş bir dizin mutlaka aynı dizin nesnesi tarafından desteklenmez.
Max Vernon

5

SQL Server istatistikleri için Microsoft Docs sayfası şunları gösterir :

Bir dizini yeniden oluşturma, birleştirme veya yeniden düzenleme gibi işlemler veri dağılımını değiştirmez. Bu nedenle, ALTER INDEX REBUILD, DBCC DBREINDEX, DBCC INDEXDEFRAG veya ALTER INDEX REORGANIZE işlemlerini gerçekleştirdikten sonra istatistikleri güncellemeniz gerekmez . Query Optimizer, bir tablodaki bir dizini yeniden oluşturduğunuzda veya ALTER INDEX REBUILD veya DBCC DBREINDEX ile görüntülediğinizde istatistikleri günceller, ancak bu istatistik güncellemesi, dizinin yeniden oluşturulmasının bir yan ürünüdür. Query Optimizer, DBCC INDEXDEFRAG veya ALTER INDEX REORGANIZE işlemlerinden sonra istatistikleri güncellemez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.