Rozmiar bazy danych - zbyt duży MDF?

10

Utrzymuję bazę danych SQL Server 2005, która zawiera około 2,9 TB danych (2 x 1,45 TB - mam schemat RAW i schemat ANALIZY, więc w zasadzie dwie kopie zebranych danych). Model odzyskiwania jest PROSTY i .ldfma prędkość 6 Gb.

Z jakiegokolwiek powodu .mdfjest to 7,5 TB. Teraz w tabeli ANALIZA są tylko 2-3 dodatkowe kolumny i niewiele NVARCHAR(MAX)kolumn, które z tego, co (mogłem błędnie zrozumieć - popraw mnie, jeśli się mylę) może powodować dodatkowe przydzielanie miejsca. Dzieje się tak po zmniejszeniu bazy danych - wcześniej było to około 9 TB. jakieś pomysły?

I proszę, daj mi znać, jeśli masz dodatkowe pytania - jestem zupełnie nowy w administrowaniu bazami danych i optymalizacji (zazwyczaj nie wykonuję tej strony pracy :)).

Wielkie dzięki!

Andrija

Andrija_Bgd
źródło
Dzięki Marc - w jakikolwiek sposób mogę przenieść tam to pytanie lub czy muszę ponownie wysłać wiadomość?
Pozdrawiam - jak pewnie się domyślacie, jestem tu nowy :)

Odpowiedzi:

11

Czy w swoich szacunkach wielkości uwzględniłeś ilość miejsca zajmowanego przez indeksy? Również jeśli masz pola tekstowe, które są ustawione jako wielobajtowe ( N[VAR]CHARzamiast [VAR]CHAR), a pliki wejściowe to UTF-8 lub zwykły jeden bajt na znak, zwiększy to twoje wymagania dotyczące pamięci nawet dwa razy. Ponadto pamiętaj, że jeśli masz klastrowany klucz / indeks w tabeli, rozmiar tego wpływa na wszystkie inne indeksy w tabeli, ponieważ zawierają one wartość klucza klastrowego dla każdego wiersza (tak by dać skrajny przykład, jeśli tabela ma NCHAR (10). ) w przypadku, gdy zrobiłaby to INT i to jest twój klastrowany klucz / indeks, nie tylko używasz dodatkowych 16 bajtów na wiersz na stronach danych, ale również marnujesz 16 bajtów na wiersz w każdym innym indeksie w tej tabeli ) .

Ponadto część miejsca zostanie przydzielona, ​​ale nieużywana, albo dlatego, że silnik DB zostawił trochę miejsca przydzielonego po usunięciu, aby można go było szybko wykorzystać do nowych danych w tej tabeli lub ponieważ wzorzec wstawiania i usuwania pozostawił wiele stron tylko część pełny.

Możesz uruchomić:

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

aby szybko sprawdzić, które stoliki zajmują miejsce.

Również EXEC sp_spaceuseduruchomienie w ramach tej DB zwróci dwa zestawy wyników. Pierwsza pokazuje całkowitą przestrzeń przydzieloną w systemie plików dla plików danych i ile z nich jest nieprzydzielone, druga pokazuje, ile przydzielonej przestrzeni jest wykorzystywane na strony danych, strony indeksu lub jest aktualnie nieużywane.

sp_spaceused zwróci również przestrzeń używaną przez dany obiekt, więc możesz zapętlić to, aby zbudować tabelę do analizy:

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

Powyższy kod wyświetli wszystkie rozmiary tabel na jednej liście plus jeden wiersz dla sum. W razie potrzeby możesz użyć różnych widoków systemu (takich jak sys.objectsi sys.dm_db_partition_statsużywanych w pierwszym zapytaniu powyżej, zobacz http://technet.microsoft.com/en-us/library/ms177862.aspx, aby uzyskać więcej szczegółów), aby uzyskać więcej szczegółów, takich jak miejsce używane przez każdy indeks.


W pliku danych znajdują się trzy klasy nieużywanego miejsca:

  1. To, co nie jest przypisane do niczego (pokazuje to w pierwszym zestawie wyników sp_spaceusedbez określonego obiektu)
  2. To, co jest przydzielone do obiektu (zarezerwowane), ale nie jest aktualnie używane (pokazuje to wynik „nieużywany” w sp_spaceuseddanych wyjściowych.
  3. Zamknięty na częściowo używanych stronach (będzie to wyglądać na wykorzystane, ponieważ wszystko jest podzielone na pojedyncze strony, jedna strona ma długość 8192 bajtów). Jest to trudniejsze do wykrycia / obliczenia. Wynika to z połączenia dwóch czynników:
    • Podziel strony. W miarę dodawania danych często kończą się puste strony (silnik pamięci może zawsze znormalizować zawartość strony, ale byłoby to bardzo nieefektywne), a po usunięciu wierszy zawartość strony nie jest automatycznie pakowana (ponownie mogą być, ale dodatkowe Obciążenie I / O jest generalnie dalekie od wartości).
    • Mechanizm pamięci masowej nie podzieli wiersza na wiele stron (wraz z rozmiarem strony, z którego pochodzi 8 192 bajtów na wiersz). Jeśli wiersze mają stały rozmiar i zajmują 1100 bajtów, to „zmarnujesz” co najmniej 492 bajty każdego bloku danych przypisanego do tej tabeli (7 wierszy zajmuje 7700 bajtów, a 8 nie pasuje, więc pozostałe bajty wygrały ” do użycia). Im szersze rzędy, tym może być gorzej. Tabele / indeksy z wierszami o zmiennej długości (które są znacznie częstsze niż wiersze o całkowicie ustalonej długości) generalnie są lepsze (ale trudniej je obliczyć).
      Kolejnym zastrzeżeniem są tutaj duże obiekty ( TEXTkolumny,[N]VARCHAR(MAX) wartości powyżej określonego rozmiaru i tak dalej), ponieważ są umieszczane poza stroną, po prostu biorąc 8 bajtów w głównym wierszu danych, aby trzymać wskaźnik do danych w innym miejscu), więc może przekroczyć limit 8192 bajtów na wiersz.

tl; dr: Szacowanie oczekiwanych rozmiarów baz danych może być o wiele bardziej zaangażowane, niż początkowo zakładać.

David Spillett
źródło
David - dziękuję bardzo za szczegółową odpowiedź! Analizuję teraz db i zarówno twoje, jak i Kennetha odpowiedzi były bardzo pomocne w moim zrozumieniu czynników wpływających na rozmiar bazy danych. Zawsze dbam o wydajność (zarówno jeśli chodzi o przyjmowanie i wykorzystanie danych), jak i informacje, które przekazaliście, były bezcenne!
Andrija_Bgd,
6

Spróbuj uruchomić sp_spaceusedbazę danych. Jako przykład zwraca:

reserved           data               index_size         unused
------------------ ------------------ ------------------ ------------------
6032 KB            2624 KB            1664 KB            1744 KB

Aby uruchomić go w bazie danych, wystarczy USEuruchomić bazę danych sp_spaceused.

Jeśli nadal pokazuje dużo niewykorzystanego miejsca, możesz ponownie spróbować zmniejszyć. Czasami zdarza mi się, że potrzeba wielu prób. Czasami też uważam, że najlepiej jest zmniejszyć pojedynczy plik, a nie bazę danych jako całość. Jednak może się okazać, że masz 2,9 TB danych i kolejne 4 + Tb indeksów, w którym to przypadku 7,5 TB jest całkiem rozsądne. Jeśli chcesz sp_spaceusedsprawdzić ilość miejsca (danych i indeksu) w każdej tabeli, możesz uruchomić również na poziomie tabeli. Możesz uruchomić go we wszystkich tabelach w bazie danych, używając następującego polecenia:

EXEC sp_msforeachtable 'EXEC sp_spaceused [?];'

Mimo, że uczciwe ostrzeżenie sp_msforeachtable jest nieudokumentowane, nie jest obsługiwane i wiadomo, że omija tabele. Z drugiej strony sam miałem z tym sporo szczęścia.

Biorąc to wszystko pod uwagę, baza danych POWINNA mieć pewien procent wolnego miejsca w zależności od oczekiwanego wzrostu. Zasadniczo chcesz mieć pewność, że masz miejsce na wzrost od 6 miesięcy do kilku lat. Będziesz także chciał sprawdzić swoje autogrowthustawienia, aby upewnić się, że są odpowiednie do twojej sytuacji. W szczególności biorąc pod uwagę rozmiar bazy danych NIE chcesz używać% autogrowth.

Kenneth Fisher
źródło
Dziękuję Ci! Użyłem sp_spaceused i wygląda na to, że rzeczywiste dane w rzeczywistości zajmują wskazaną ilość miejsca, choć może to zabrzmieć dziwnie, biorąc pod uwagę faktyczny rozmiar załadowanych plików płaskich ... Wskaźniki są małe (nie mam stworzyłem dodatkowe, ponieważ byłyby bardziej przeszkodą niż pomocą w moim przypadku), więc myślę, że to tylko duże tabele… Dzięki za pomoc!
Andrija_Bgd,
Bazy danych zajmują więcej miejsca niż pliki płaskie. Na strukturę wierszy i tabel nakłada się pewien narzut oraz pewna ilość odpadów z powodu struktury strony.
Kenneth Fisher
-1

Za pomocą SQL Management Studio: 1. Kliknij prawym przyciskiem myszy bazę danych, a następnie 2. Kliknij Zadania-> Zmniejsz -> Pliki

Zobaczysz okno dialogowe pokazujące: Obecnie przydzielone miejsce b. Dostępne wolne miejsce + (% za darmo)

Jeśli Twój% Free wynosi ponad 50%, możesz rozważyć zmniejszenie pliku. Widziałem ten hit aż 90%. Jeśli zdecyduję się zmniejszyć plik, zwykle ustawiam go na 2 lub 3 koncerty więcej niż aktualnie przydzielone miejsce. Większość moich baz danych ma mniej niż 50 sztuk. Więc jeśli masz znacznie większy plik, możesz zwiększyć go do 10 koncertów. Zwykle martwię się tylko o zmniejszenie, jeśli zamierzam przenieść bazę danych na inny serwer, możesz przeczytać wszystko o zmniejszaniu się problemów na dowolnej stronie sql.

Clark Vera
źródło