Dalam perkiraan ukuran Anda, sudahkah Anda memperhitungkan jumlah ruang yang diambil oleh indeks? Juga jika Anda memiliki bidang teks yang ditetapkan sebagai multi-byte ( N[VAR]CHAR
bukan [VAR]CHAR
) dan file input UTF-8 atau polos satu-byte-per-karakter maka itu akan mendorong persyaratan penyimpanan Anda hingga faktor dua. Lebih jauh lagi ingat bahwa jika Anda memiliki kunci / indeks berkerumun di tabel ukuran ini mempengaruhi semua indeks lain di atas meja karena mereka menyertakan nilai kunci berkerumun untuk setiap baris (jadi untuk memberikan contoh ekstrem jika tabel memiliki NCHAR (10 ) kunci di mana INT akan dilakukan dan itu adalah kunci / indeks berkerumun Anda, Anda tidak hanya menggunakan tambahan 16 byte per baris di halaman data, Anda juga membuang 16 byte per baris di setiap indeks lain pada tabel itu ) .
Juga, beberapa ruang akan dialokasikan tetapi tidak digunakan, baik karena mesin DB telah meninggalkan beberapa ruang yang dialokasikan setelah dihapus sehingga dapat digunakan kembali dengan cepat untuk data baru dalam tabel itu atau karena pola memasukkan dan menghapus telah meninggalkan banyak halaman hanya bagian penuh.
Anda dapat menjalankan:
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
untuk melihat sekilas tabel apa yang mengambil ruang.
Juga EXEC sp_spaceused
berjalan di dalam DB yang akan mengembalikan dua set hasil. Yang pertama daftar total ruang yang dialokasikan dalam sistem file untuk file data dan berapa banyak yang tidak dialokasikan, yang kedua daftar berapa banyak ruang yang dialokasikan digunakan untuk halaman data, untuk halaman indeks, atau saat ini tidak digunakan.
sp_spaceused
akan mengembalikan ruang yang digunakan oleh objek yang diberikan juga, sehingga Anda dapat mengulang ini untuk membangun tabel untuk analisis:
-- 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
Kode di atas akan menampilkan semua ukuran tabel dalam satu daftar, ditambah satu baris untuk total. Jika perlu Anda dapat menggunakan berbagai tampilan sistem (seperti sys.objects
dan sys.dm_db_partition_stats
digunakan dalam permintaan pertama di atas, lihat http://technet.microsoft.com/en-us/library/ms177862.aspx untuk lebih jelasnya) untuk mendapatkan detail lebih lanjut seperti ruang yang digunakan oleh setiap indeks.
Ada tiga kelas ruang yang tidak digunakan dalam file data:
- Apa yang tidak dialokasikan untuk apa pun (ini menunjukkan di hasil pertama dari
sp_spaceused
tanpa objek yang ditentukan)
- Apa yang dialokasikan untuk objek (dilindungi undang-undang) tetapi saat ini tidak digunakan (ini menunjukkan dalam "tidak digunakan" dalam
sp_spaceused
output.
- Itu terkunci di halaman yang digunakan sebagian (ini akan terlihat untuk digunakan karena semuanya dialokasikan dalam potongan halaman tunggal, satu halaman menjadi 8.192 byte panjang). Ini lebih sulit untuk dideteksi / dihitung. Ini karena campuran dua faktor:
- Halaman terpisah. Ketika data ditambahkan, Anda sering berakhir dengan bagian halaman yang kosong (mesin penyimpanan selalu dapat menormalkan isi halaman, tetapi ini akan sangat tidak efisien), dan karena baris dihapus, konten halaman tidak secara otomatis dikemas (sekali lagi mungkin, tetapi tambahan Beban I / O umumnya jauh dari layak).
- Mesin penyimpanan tidak akan membagi satu baris menjadi beberapa halaman (ini bersama dengan ukuran halaman dari mana batas 8.119 byte per baris berasal dari). Jika baris Anda berukuran tetap dan masing-masing mengambil 1.100 byte, maka Anda akan "membuang" setidaknya 492 byte dari setiap blok data yang dialokasikan ke tabel itu (7 baris mengambil 7.700 byte dan yang ke-8 tidak cocok sehingga sisanya akan menang ' t digunakan). Semakin lebar baris, semakin buruk hal ini. Tabel / indeks dengan baris panjang variabel (yang jauh lebih umum daripada yang benar-benar panjang tetap) umumnya lebih baik (tetapi kurang mudah untuk menghitung masalah untuk).
Peringatan lain di sini adalah benda besar ( TEXT
kolom,[N]VARCHAR(MAX)
nilai-nilai di atas ukuran tertentu dan seterusnya) karena mereka ditempatkan di luar halaman, hanya mengambil 8 byte di data baris utama untuk menahan pointer ke data di tempat lain) sehingga dapat mematahkan 8.192 byte-per-baris-batas.
tl; dr: Memperkirakan ukuran basis data yang diharapkan bisa menjadi jauh lebih banyak terlibat daripada yang biasanya diasumsikan pada awalnya.