SQL: Indeksacja dużej tabeli

10-mar-2016

Chyba niestety dość częsty scenariusz…. Duża baza, no cóż zdarza się. W dużej bazie duża tabela – no cóż bywa. I oprócz tego… prawie nic więcej. Tak jakby ktoś pozbierał wszystkie excele z firmy i zapisał je w bazie. Niestety jedyny indeks w tabeli się pofragmentował. Nie ma problemu, trzeba uruchomić reindeksację. Ale o reindeksacji dużych obiektów wiadomo:

Indexes with more than 128 extents are rebuilt in two separate phases: logical and physical. In the logical phase, the existing allocation units used by the index are marked for deallocation, the data rows are copied and sorted, then moved to new allocation units created to store the rebuilt index. In the physical phase, the allocation units previously marked for deallocation are physically dropped in short transactions that happen in the background, and do not require many locks.

(https://technet.microsoft.com/en-us/library/ms189858(v=sql.110).aspx)

Ile więc potrzeba miejsca na reindeksację? Jeśli nie masz ochoty czytać dalej, to mniej więcej tyle samo, co reindeksowany obiekt aktualnie zajmuje. A właściwie to trochę więcej, dajmy na to 120%. Podczas reindeksowania można posłużyć się opcją SORT_IN_TEMPDB, która ma pewien wpływ na ilość potrzebnego miejsca. Jednak opcja ta nie spowoduje, że miejsce jest potrzebne tylko w temp! Nadal potrzebujesz miejsca w bazie. Nie pomoże również dostępna w edycji ENTERPRISE opcja ONLINE. Będzie nawet trochę gorzej, bo opccja online powoduje, że SQL gwarantuje możliwość korzystania z indeksu podczas reindeksacji. Potrzebuje więc, aby zbudować dodatkową tabelę mapującą, która pozwoli odpowiadać na zapytania użytkowników podczas indeksowania.

A teraz już dokładniej:

  • żeby zindeksować 10 GB musisz obok istniejącego indeksu stworzyć jego kopię. Jeśli kopia jest tworzona z FILL FACTOR 80% to do rozmiaru trzeba dorzucić 20%
  • podczas budowania indeksu dane są roboczo sortowane i tu mamy 2 przypadki:
    • Nie było opcji SORT_IN_TEMPDB – wtedy te dodatkowe obiekty są tworzone w bieżącej bazie. Ilość miejsca jest zależna od wielkości klucza podstawowego. Za to w tym scenariuszu tempdb nie cierpi
    • Była opcja SORT_IN_TEMPDB – wtedy nowy indeks powstaje i tak w oryginalnej bazie danych, co łącznie z FILL FACTOR znowu sprowadza nas do 120% wielkości indeksu. Jednak dane robocze są sortowane w tempdb, a jeśli wydajnie skonfigurowano tempdb (jako oddzielny szybki napęd), to takie indeksowanie skończy się trochę szybciej. Niestety tempdb potrzebuje teraz więcej miejsca i jest dociążone. Użycie tej opcji spowoduje więc, że sumarycznie będzie potrzebne jeszcze więcej miejsca na dysku.
  • Jeśli korzystasz z edycji ENTERPRISE i decydujesz się skorzystać z opcji ONLINE, to  płacisz za to znowu dodatkowym miejscem.

Artykuł https://technet.microsoft.com/en-us/library/ms191183(v=sql.105).aspx analizuje te przypadki o wiele dokładniej. Dla mnie wniosek jest jeden. W przypadku takich baz i takich tabel, zasada, która będzie zakłądać, że w każdej bazie danych mam mieć co najmniej (czytaj około) 20% wolnego miejsca, bierze w łeb. W normalnym życiu bazy, 20% zapasu wystarczy, ale przy reindeksacji, potrzeba będzie około 1.5 raza tyle co największy obiekt….

Polecam też: https://blogs.msdn.microsoft.com/sqlserverstorageengine/2007/01/24/checkdb-part-7-how-long-will-checkdb-take-to-run/

Komentarze:

  1. Rafał napisał,

    dobre!!!!

Autor: Rafał Kraik