Trong ước tính kích thước của bạn, bạn đã tính đến dung lượng của các chỉ mục chưa? Ngoài ra, nếu bạn có các trường văn bản được đặt là nhiều byte ( N[VAR]CHAR
chứ không phải [VAR]CHAR
) và các tệp đầu vào là UTF-8 hoặc một byte cho mỗi ký tự thì điều đó sẽ đẩy yêu cầu lưu trữ của bạn lên đến hai nhân tố. Hơn nữa, hãy nhớ rằng nếu bạn có một khóa / chỉ mục được nhóm trên một bảng thì kích thước của nó sẽ ảnh hưởng đến tất cả các chỉ mục khác trên bảng vì chúng bao gồm giá trị khóa được phân cụm cho mỗi hàng (vì vậy hãy đưa ra một ví dụ cực đoan nếu một bảng có NCHAR (10 ) trong đó một INT sẽ làm và đó là khóa / chỉ mục được nhóm của bạn, bạn không chỉ sử dụng thêm 16 byte mỗi hàng trong các trang dữ liệu mà bạn còn lãng phí 16 byte mỗi hàng trong mỗi chỉ mục khác trên bảng đó ) .
Ngoài ra, một số không gian sẽ được phân bổ nhưng không được sử dụng, vì công cụ DB đã để lại một số không gian được phân bổ sau khi xóa để có thể sử dụng lại nhanh chóng cho dữ liệu mới trong bảng đó hoặc do mẫu chèn và xóa chỉ còn lại một số trang đầy.
Bạn có thể chạy:
SELECT o.name
, SUM(ps.reserved_page_count)/128.0 AS ReservedMB
, SUM(ps.used_page_count)/128.0 AS UsedMB
, SUM(ps.reserved_page_count-ps.used_page_count)/128.0 AS DiffMB
FROM sys.objects o
JOIN sys.dm_db_partition_stats ps ON o.object_id = ps.object_id
WHERE OBJECTPROPERTYEX(o.object_id, 'IsMSShipped') = 0
GROUP BY o.name
ORDER BY SUM(ps.reserved_page_count) DESC
để có được một cái nhìn nhanh chóng về những gì bảng đang chiếm không gian.
Cũng EXEC sp_spaceused
chạy trong DB đó sẽ trả về hai tập kết quả. Cái đầu tiên liệt kê tổng dung lượng được phân bổ trong hệ thống tệp cho các tệp dữ liệu và bao nhiêu phần không được phân bổ, phần thứ hai liệt kê bao nhiêu không gian được phân bổ được sử dụng cho các trang dữ liệu, cho các trang chỉ mục hoặc hiện không được sử dụng.
sp_spaceused
cũng sẽ trả về không gian được sử dụng bởi một đối tượng nhất định, vì vậy bạn có thể lặp vòng này để xây dựng bảng để phân tích:
-- TEMP TABLES FOR ANALYSIS
CREATE TABLE #tTables (sName NVARCHAR(MAX), iRows BIGINT, iReservedKB BIGINT, iDataKB BIGINT, iIndexKB BIGINT, iUnusedKB BIGINT)
CREATE TABLE #tTmp (sName NVARCHAR(MAX), iRows BIGINT, sReservedKB NVARCHAR(MAX), sDataKB NVARCHAR(MAX), sIndexKB NVARCHAR(MAX), sUnusedKB NVARCHAR(MAX))
-- COLLECT SPACE USE PER TABLE
EXEC sp_msforeachtable 'INSERT #tTmp EXEC sp_spaceused [?];'
-- CONVERT NUMBER-AS-TEXT COLUMNS TO NUMBER TYPES FOR EASIER ANALYSIS
INSERT #tTables SELECT sName, iRows
, CAST(REPLACE(sReservedKB, ' KB', '') AS BIGINT)
, CAST(REPLACE(sDataKB , ' KB', '') AS BIGINT)
, CAST(REPLACE(sIndexKB , ' KB', '') AS BIGINT)
, CAST(REPLACE(sUnusedKB , ' KB', '') AS BIGINT)
FROM #tTmp
DROP TABLE #tTmp
-- DO SOME ANALYSIS
SELECT sName='TOTALS', iRows=SUM(iRows), iReservedKB=SUM(iReservedKB), iDataKB=SUM(iDataKB), iIndexKB=SUM(iIndexKB), iUnusedKB=SUM(iUnusedKB) FROM #tTables ORDER BY sName
SELECT * FROM #tTables ORDER BY iReservedKB DESC
-- CLEAN UP
DROP TABLE #tTables
Đoạn mã trên sẽ xuất ra tất cả các kích thước bảng trong một danh sách, cộng với một hàng cho tổng số. Nếu cần, bạn có thể sử dụng các chế độ xem hệ thống khác nhau (thích sys.objects
và sys.dm_db_partition_stats
được sử dụng trong truy vấn đầu tiên ở trên, xem http://technet.microsoft.com/en-us/l Library / ms177862.aspx để biết thêm chi tiết) để biết thêm chi tiết như không gian được sử dụng bởi mỗi chỉ số.
Có ba lớp không gian chưa sử dụng trong một tệp dữ liệu:
- Cái không được phân bổ cho bất cứ thứ gì (điều này hiển thị trong tập kết quả đầu tiên từ
sp_spaceused
không có đối tượng được chỉ định)
- Cái được phân bổ cho một đối tượng (dành riêng) nhưng hiện không được sử dụng (điều này thể hiện trong số lượng "không sử dụng" trong
sp_spaceused
đầu ra.
- Điều đó bị khóa trong các trang được sử dụng một phần (điều này sẽ được sử dụng vì mọi thứ được phân bổ trong các đoạn trang đơn, một trang dài 8.192 byte). Điều này khó phát hiện / tính toán hơn. Đó là do sự kết hợp của hai yếu tố:
- Chia trang. Khi dữ liệu được thêm vào, bạn thường kết thúc với một phần trang trống (công cụ lưu trữ luôn có thể bình thường hóa nội dung trang, nhưng điều này sẽ rất không hiệu quả) và vì các hàng bị xóa nên nội dung trang không được tự động đóng gói (có thể là một lần nữa Tải I / O thường không có giá trị).
- Công cụ lưu trữ sẽ không phân chia một hàng trên nhiều trang (điều này cùng với kích thước trang có giới hạn 8.192 byte trên mỗi hàng xuất phát). Nếu các hàng của bạn có kích thước cố định và lấy 1.100 byte mỗi hàng thì bạn sẽ "lãng phí" ít nhất 492 byte của mỗi khối dữ liệu được phân bổ cho bảng đó (7 hàng mất 7,700 byte và 8 byte sẽ không phù hợp để các byte còn lại giành được ' t được sử dụng). Các hàng càng rộng, điều này có thể tồi tệ hơn. Các bảng / chỉ mục có các hàng có chiều dài thay đổi (phổ biến hơn nhiều so với các chiều dài cố định hoàn toàn) thường công bằng hơn (nhưng ít dễ dàng hơn để tính toán vấn đề).
Một cảnh báo khác ở đây là các đối tượng lớn ( TEXT
cột,[N]VARCHAR(MAX)
các giá trị trên một kích thước nhất định, v.v.) khi chúng được đặt ngoài trang, chỉ cần lấy 8 byte trong dữ liệu hàng chính để giữ một con trỏ tới dữ liệu ở nơi khác) để có thể phá vỡ giới hạn 8.192 byte mỗi hàng.
tl; dr: Ước tính kích thước cơ sở dữ liệu dự kiến có thể liên quan nhiều hơn so với giả định ban đầu.