Bu gerçekten bu kadar çılgın görünmüyor, ancak bazı UI iletişim kutularının tamamen güncel bilgilere sahip olmayabileceğini unutmayın (bu yüzden DBCC GÜNCELLEME gibi şeylere sahibiz ) ve yuvarlama da bunlardan bazılarında yer alabilir hesaplamaları. Son olarak, iletişim kutuları size tüm veritabanının toplam alanını gösterir , ancak ayrılmamış alan yalnızca veri dosyaları için hesaplanır , günlük için hesaplanmaz .
Bazı şeyleri birleştirelim.
- Veritabanı özellikleri ve shrink veritabanı aynı şeyi gösterir (yine de shrink veritabanı arayüzünde olmanız gerekmez!).
- Veritabanı dosyası özellikleri, eklemeden önce yuvarlama ile muhtemelen 1'de 91.31 olan 17 + 75 = 92 değerini gösterir.
- Ayrılan alan için, tek tek dosyalar için shrink 16.38 + 74.94 = 91.32'yi gösterir - yine, muhtemelen orada yuvarlama, aksi takdirde tam olarak eşleşen 1.
- Kullanılabilir alan için, tek tek dosyalar için küçült, gerçek bir tutarsızlıktan şüphelendiğim tek yer ve bunun nedeni kullanıcı arayüzünün verilerini nereden aldığı konusunda tutarsız olması ve bu yerlerin bazılarının DBCC GÜNCELLEMESİ gerektiren önbelleğe alınmasıdır.
Bu farklı diyalogların AdventureWorks2012 yerel kopyam için ne çalıştırdığına bir bakayım (bazı tablolar bu komut dosyasından büyütülmüş olarak ).
EXEC sp_spaceused;
Bu döndürür (yalnızca ilk sonuç kümesi):
database_size unallocated space
------------- -----------------
1545.81 MB 6.67 MB
Temel olarak, bu - izleme yoluyla onayladığım - kabaca veritabanı özellikleri ve veritabanı küçültme iletişim kutularından yürütülen aynı sorguyu çalıştırır (saklı yordamdan alakasız parçaları oydum ve matematik temsil etmek için bir dış sorgu ekledim SSMS'nin görüntüleme için yaptığı):
SELECT database_size = DbSize*8.0/1024 + LogSize*8.0/1024,
[unallocated space] = (DbSize-SpaceUsed)*8.0/1024
FROM
(
SELECT
(SELECT SUM(CAST(df.size as float)) FROM sys.database_files AS df
WHERE df.type in ( 0, 2, 4 ) ) AS [DbSize],
SUM(a.total_pages) AS [SpaceUsed],
(SELECT SUM(CAST(df.size as float)) FROM sys.database_files AS df
WHERE df.type in (1, 3)) AS [LogSize]
FROM sys.partitions p
join sys.allocation_units a on p.partition_id = a.container_id
left join sys.internal_tables it on p.object_id = it.object_id
) AS x;
Bu bir eşleşme döndürür:
database_size unallocated space
------------- -----------------
1545.8125 6.671875
Bu iletişim kutularının tümü bu bilgileri doğru bir şekilde gösterir. Veritabanı Özellikleri iletişim kutusu:
Veritabanını Küçült iletişim kutusu:
Shrink dosyası iletişim kutuları ise biraz farklı bir sorgu çalıştırır (yine bu kolaylık sağlamak için oyulmuştur / uyarlanmıştır):
SELECT SUBSTRING(name, CHARINDEX('_',name)+1, 4),
[Currently allocated space] = size/1024.0,
[Available free space] = (Size-UsedSpace)/1024.0
FROM
(
SELECT s.name,
CAST(FILEPROPERTY(s.name, 'SpaceUsed') AS float)*CONVERT(float,8) AS [UsedSpace],
s.size * CONVERT(float,8) AS [Size]
FROM sys.database_files AS s
WHERE (s.type IN (0,1))
) AS x;
Ayrıca, DMV yerine bir işlevden boyut verileri almanın yanı sıra, tahminlerin filestream / hekaton gibi yeni dosya türleri için güncellenmediğini unutmayın.
Sonuçlar:
Currently allocated space Available free space
---- ------------------------- --------------------
Data 1517 7.9375 -- wrong
Log 28.8125 25.671875 -- wrong
Sorun, FILEPROPERTY()
güncel olması garanti edilmeyen işlevdir ( DBCC UPDATEUSAGE(0);
çalıştırıldıktan sonra bile ; daha aşağıda). Bu, iletişim kutularındaki yanıltıcı bilgilerle sonuçlanır:
Yine, sadece toplam veritabanı boyutunu ölçtüğünden, 6.67 MB'nin hiçbir zaman gerçekten doğru olmadığını unutmayın; ayrılan sayfa sayısı, günlüğü tamamen göz ardı eder.
Dürüst olmak gerekirse, veritabanında kullanılan alanın doğru bir şekilde raporlanmasını istiyorsanız, bunu anlamak için her türlü farklı sorguyu çalıştıran mickey mouse kullanıcı arayüzlerini kullanmayı bırakın ve bilgi almak için shrink dosyası iletişim kutularını kullanmayı bırakın. Bunlar, bazı durumlarda açıkça eski veri sorunlarına tabidir. Güvenebileceğiniz bir kaynağa karşı gerçek bir sorgu çalıştırın. İşte tercih ettiğim şey:
DECLARE @log_used DECIMAL(19,7);
CREATE TABLE #x(n SYSNAME, s DECIMAL(19,7), u DECIMAL(19,7), b BIT);
INSERT #x EXEC('DBCC SQLPERF(LogSpace);');
SELECT @log_used = u FROM #x WHERE n = DB_NAME();
DROP TABLE #x;
DECLARE @data_used DECIMAL(19,7);
SELECT @data_used = SUM(a.total_pages)*8/1024.0
FROM sys.partitions AS p
INNER JOIN sys.allocation_units AS a
ON p.[partition_id] = a.container_id;
;WITH x(t,s) AS
(
SELECT [type] = CASE
WHEN [type] IN (0,2,4) THEN 'data' ELSE 'log' END,
size*8/1024.0 FROM sys.database_files AS f
)
SELECT
file_type = t,
size = s,
available = s-CASE t WHEN 'data' THEN @data_used ELSE @log_used END
FROM x;
Bu sorgu, çok tanıdık görünmesi gereken üç sayı ve olmaması gereken bir sayı döndürür:
file_type size available
--------- ----------- ----------
data 1517.000000 6.6718750
log 28.812500 17.9008512
DBCC SQLPERF'nin , örneğin çalıştırdıktan sonra alan kullanımı ile ilgili sorunlara da eğilimli olduğunu unutmayın :
DBCC UPDATEUSAGE(0);
Yukarıdaki sorgu bunun yerine verir:
file_type size available
--------- ----------- ----------
data 1517.000000 8.0781250
log 28.812500 17.8669481
sp_spaceused
şimdi 1545.81 MB / 8.08 MB
yine de eşleşen sayıları verir ( ), yine de - bu sadece veri dosyalarında bulunan alan ve veritabanı özelliği ve veritabanı küçültme iletişim kutuları da "doğru" olsa da (küçültme dosya iletişim kutuları hala kapalı - FILEPROPERTY()
hiç etkilenmiyor gibi görünüyor UPDATEUSAGE
):
Oh, ve aynı zamanda Windows Gezgini'nin bu dosyalar hakkında ne düşündüğünü gösterebilir, böylece MB'yi belirlemek için yapılan hesaplamalar ile ilgili olabilir:
Tüm bunların ne kadar doğru olması gerektiği elbette bilgilerle ne yapacağınıza bağlıdır.