Jakie są obecnie najlepsze praktyki dotyczące zmiany rozmiaru varchar w SQL Server?

12

Próbuję zrozumieć najlepszy sposób, aby zdecydować, jak duże powinny być kolumny varchar, zarówno z punktu widzenia przechowywania, jak i wydajności.

Wydajność Wydaje się
, że z moich badańtego varchara (maks.) należy używać tylko wtedy, gdy naprawdę go potrzebujesz; to znaczy, jeśli kolumna musi pomieścić więcej niż 8000 znaków, jednym z powodów jest brak indeksowania (chociaż jestem trochę podejrzliwy co do indeksowania pól varchar w ogóle. Jestem jednak całkiem nowy w zasadach DB, więc może to nieuzasadnione ) i kompresja (bardziej dotyczy przechowywania). W rzeczywistości ludzie wydają się zalecać używanie tylko tego, czego potrzebujesz, podczas wykonywania varchar (n) .... przewymiarowanie jest złe, ponieważ zapytania muszą uwzględniać maksymalny możliwy rozmiar. Ale stwierdzono również, że silnik wykorzysta połowę wskazanego rozmiaru jako oszacowanie średniego rzeczywistego rozmiaru danych. Oznaczałoby to, że należy określić na podstawie danych, jaki jest średni rozmiar, podwoić go i użyć jako n. Jednak w przypadku danych o bardzo niskiej, ale niezerowej zmienności, oznacza to do 2x przewymiarowania ponad maksymalny rozmiar, co wydaje się dużo, ale może nie jest? Docenione będą mile widziane.

Przechowywanie
Po przeczytaniu o tym, jak działa przechowywanie w rzędzie a poza rzędem, i pamiętając, że faktyczne przechowywanie jest ograniczone do rzeczywistych danych, wydaje mi się, że wybór n ma niewielki lub żaden wpływ na przechowywanie (poza upewniając się, że jest wystarczająco duży, aby pomieścić wszystko). Nawet użycie varchar (max) nie powinno mieć żadnego wpływu na przechowywanie. Zamiast tego celem może być ograniczenie rzeczywistego rozmiaru każdego wiersza danych do ~ 8000 bajtów, jeśli to możliwe. Czy to dokładny odczyt rzeczy?

Kontekst
Niektóre z danych naszych klientów nieco się wahają, dlatego generalnie poszerzamy kolumny nieco, niż powinny być, powiedzmy, 15-20% większe, dla tych kolumn. Zastanawiałem się, czy są jakieś inne szczególne względy; na przykład ktoś, z kim pracuję, powiedział mi, żebym używał rozmiarów 2 ^ n - 1 (nie znalazłem dowodów, że coś takiego jest ....)

Mówię o początkowym tworzeniu tabeli. Klient powie nam, że zacznie przesyłać nam nową tabelę i wyśle ​​przykładowe dane (lub tylko pierwszy zestaw danych produkcyjnych), na które spojrzymy i utworzy tabelę na naszym końcu, aby przechowywać dane. Chcemy, aby nasza tabela obsługiwała przyszły import, a także to, co jest w próbie. Ale niektóre rzędy muszą się wydłużyć, więc je wypełniamy.

Pytanie brzmi, ile i czy istnieją wytyczne techniczne?

aristotle2600
źródło
MongoDB wykorzystuje przydział 2 ^ n dysku dla dokumentu. SQL Server nie używa tej strategii.
Michael Green,

Odpowiedzi:

19

Bez względu na konkretny typ danych musisz mieć możliwość przechowywania dowolnych żądań aplikacji, które mają być przechowywane. Nie możesz określić czegoś mniejszego niż maksymalny rozmiar tego, co faktycznie zostanie zapisane.

Nie musisz też, ani nie chcesz, określać długości kolumny większej niż maksymalny rzeczywisty rozmiar, który będzie przechowywany z różnych powodów: przydział pamięci zapytania, potencjalnie wypełnienie maksymalnego rozmiaru wiersza i nie pozostawianie miejsca na dodanie kolumn w przyszłość itp.

Prawda, łańcuch o zmiennej długości i kolumny binarne nie mają wpływu na pamięć, jaki mają typy danych o stałej długości (ciąg / binarny / numeryczny / data / itp.) (Chociaż niektóre z tych implikacji można unieważnić przez kompresję danych lub użycie SPARSEdefinicji kolumny opcja). Jednak, jak wskazałeś, nawet jeśli nie ma to bezpośredniego wpływu na pamięć, nadal istnieje wpływ na wydajność zawyżania wymaganej pamięci dla zapytań.

Bądź rozsądny. Używać tylko tego, czego potrzebujesz. Można rozważyć, czy istnieje duże prawdopodobieństwo, że długość kolumny będzie musiała wzrosnąć w najbliższej przyszłości, ale należy pamiętać, że łatwiej jest powiększyć rozmiar kolumny niż zmniejszyć jej rozmiar. Tak, część pracy będzie wymagała zaangażowania, ale ponieważ praca ta jest jedynie „potencjalna”, podczas gdy implikacje nadmiernego rozmiaru są „rzeczywiste”, często najlepiej jest zdefiniować kolumny w oparciu o to, czego naprawdę potrzebujesz, a nie to, co być może -sorta myśli, że możesz potrzebować w przyszłości. Wiele omawianych zmian nigdy się nie zdarza i często nie można przewidzieć wymaganych zmian. Idź z tym, co wiesz.

Zamiast tego celem może być ograniczenie rzeczywistego rozmiaru każdego wiersza danych do ~ 8000 bajtów, jeśli to możliwe.

Nie jestem do końca pewien, o co tu chodzi. SQL Server fizycznie ograniczy Cię do nieco ponad 8000 bajtów. Używanie typów LOB - VARCHAR(MAX), NVARCHAR(MAX), VARBINARY(MAX), XML, i przestarzałe TEXT, NTEXTi IMAGEtypy - umożliwiają wykraczając poza tym ograniczenie początkowego rozmiaru strony, ale to tylko ze względu na umieszczenie wskaźnika (16 lub więcej bajtów, w zależności od rodzaju, oraz w zależności od rozmiar wartości przechowywanej poza wierszem podczas używania MAXtypów). Rzeczywisty fizyczny limit strony danych nie zmienił się.

Twoim celem powinno być wykorzystanie jak najmniejszej ilości fizycznej przestrzeni do przechowywania tego, co aplikacja / firma potrzebuje do przechowywania, bez przerywania lub obcinania, tak aby niekompletna wartość straciła znaczenie lub spowodowała problemy na dalszych etapach. Jeśli potrzebujesz przechowywać 12 000 znaków, użyj VARCHAR(MAX)tego, ponieważ jest to potrzebne. Jeśli przechowujesz numer telefonu lub kod pocztowy / pocztowy, korzystanie z niego byłoby nierozsądne VARCHAR(100)i nieodpowiedzialne VARCHAR(MAX).

niektóre dane naszych klientów nieco się wahają, dlatego generalnie poszerzamy kolumny nieco, niż powinny być, powiedzmy, 15-20% większe dla tych kolumn. Zastanawiałem się, czy są jakieś inne szczególne względy;

Czy wszystkie systemy nie mają przynajmniej niektórych danych, które się zmieniają? Każdy system, który przechowuje nazwisko osoby, byłby kwalifikowany, prawda? Istnieje dość duża zmienność długości nazw. A potem masz kogoś takiego jak Prince, który zmienia nazwę na symbol, a teraz masz zupełnie inny problem, który nie jest długością. Tak właśnie jest.

Ale, aby przez chwilę grać w adwokata diabła: w jaki sposób wartość „15-20% większa niż to, co jest potrzebne”, może nie być faktycznie potrzebną wartością? Powiedzmy, że toczy się dyskusja na temat dodawania nowej kolumny, a ktoś sugeruje 50 znaków, a następnie ktoś inny mówi: „cóż, 20% więcej to 60, więc zróbmy 60, ponieważ ktoś może mieć 60”. Jeśli prawdą jest, że klient może mieć 60 lat, wówczas 60 jest i zawsze było rzeczywistą potrzebną wartością, a 50 było błędem przez cały czas.

Oczywiście pomogłoby to, gdyby istniały jakieś wskazówki co do źródła danych, ponieważ:

  1. jeśli utworzysz „URL” 1024 i ktoś potrzebuje 1060, to musi to być 1060 (podobnie, jeśli tworzysz URL VARCHARi dostajesz skargi, że psuje znaki Unicode, które są teraz dozwolone w nazwach domen, to musiało tak być NVARCHAR), ale
  2. jeśli ktoś chce dodać 1000 znaków do pola komentarza o limicie 500 znaków, to wciąż musi to być tylko 500. Ludzie mogą być mniej gadatliwi w komentarzach (dla mnie ogromne wyzwanie ;-), ale ProductSKUlepiej być na tyle duży, aby zmieścił się w nich wszystkich jednostek SKU klienta.

Mówię o początkowym tworzeniu tabeli. Klient powie nam, że zacznie wysyłać nam nową tabelę i wysyła przykładowe dane (lub tylko pierwszy zestaw danych produkcyjnych), na które patrzymy i tworzy tabelę na naszym końcu, aby przechowywać dane. Chcemy, aby nasza tabela obsługiwała przyszły import, a także to, co jest w próbie. Ale niektóre rzędy muszą się wydłużyć, więc je wypełniamy. Pytanie brzmi, ile i czy istnieją wytyczne techniczne?

Robisz tutaj wiele założeń. Pewnie niektóre pola mogą się powiększyć. Ale z drugiej strony mogą nie. Lub niektóre mogą się zmniejszyć. Niektórzy mogą zmienić się z nie-Unicode na Unicode (gdy zdadzą sobie sprawę, że świat się zmniejsza i nie można zakładać, że nazwiska będą miały tylko podstawowe znaki ASCII / US English). Lub mogą przestać wysyłać pole. Lub mogą dodać jedno lub więcej pól w przyszłości. Dowolna kombinacja tego i innych rzeczy. Dlaczego więc skupiać się tylko na VARCHARkolumnach? Co zrobić, jeśli obecnie wysyłają INTwartość i za rok lub dwa osiągają maksymalną wartość i zaczynają wysyłać BIGINT? Co jeśli mają pole „status” o wartościach 0–5. Po prostu zakładaszINTktóry jest „wyściełany”, ponieważ pozwala na wzrost, ale prawdopodobnie powinien być TINYINT?

Jedyną rzeczą, którą możesz bezpiecznie przewidzieć, jest to, że próba przewidzenia, jak zmienią się dane Twoich klientów, będzie błędna częściej niż poprawna. A bycie poprawnym to kwestia szczęścia / zbiegów okoliczności (jeśli nie szczęście, to po prostu idź zagrać na loterii;).

Tak więc wytyczna jest następująca:

  1. Nie trać czasu i energii na próby odpowiedzi na pytanie, na które nie można odpowiedzieć.
  2. Zamiast tego skup się na uzyskaniu jak największej ilości informacji na temat rzeczywistych danych klienta i idź z tym (tj. Na podstawie decyzji opartych na danych ;-).

Masz już przykładowe dane, świetnie. Nie zapominaj jednak, że masz również dane kontaktowe klienta: telefon i / lub e-mail. Skontaktować się z nimi! Zapytaj ich o specyfikację danych (tak jak twój system, dane aktualnie w ich systemie mogą mieć maksymalną długość 35, ale w ich systemie jest to zdefiniowane jako VARCHAR(50), a ich system zaakceptuje do tej długości, w takim przypadku powinieneś użyć 50). Zapytaj ich, czy mają jakieś krótkoterminowe plany zmiany oraz o te typy danych (typ i / lub rozmiar).

Solomon Rutzky
źródło
1
Zgadzam się z Solomonem, @ Aristotle2600 - możesz jednak rzucić okiem na moją odpowiedź na pytanie dotyczące różnic między varchar(255)a varchar(256)dla dalszych rozważań
Max Vernon
Dzięki, miałem wrażenie, że byłoby to coś takiego, a „używanie tylko tego, czego potrzebujesz” to po prostu dobra praktyka zarządzania zasobami dookoła. Jednak niektóre dane naszych klientów nieco się zmieniają, dlatego generalnie poszerzamy kolumny nieco, niż powinny być, powiedzmy, 15-20% większe dla tych kolumn. Zastanawiałem się, czy są jakieś inne szczególne względy; na przykład ktoś, z kim pracuję, powiedział mi, żebym używał rozmiarów 2 ^ n - 1 (nie znalazłem dowodów, że coś takiego jest ....). Ale wygląda na to, że nie ma nic innego niż utrzymanie rzeczy tak małych, jak to możliwe.
aristotle2600
1
@ aristotle2600 Nie wiem, jak zastosować „2 ^ n - 1”, ale wciąż muszę zapytać: czy teoretycznie możliwe jest stworzenie czegoś większego, niż powinien być? Czy ten 15-20% większy rozmiar nie byłby tym, który musiał być, aby się nie złamać? ;-). Jestem pewien, że pomogłoby to, gdybyś był bardziej jawny w źródle danych, ponieważ a) jeśli podasz „URL” 1024 i ktoś potrzebuje 1060, to musi to być 1060, ale b) jeśli ktoś chce dodać 1000 znaków do pola komentarza o limicie 500 znaków, to wciąż musi to być tylko 500. Ludzie mogą wpisać mniej komentarzy, ale SKU produktu powinno być wystarczająco duże.
Solomon Rutzky
@ aristotle2600 Właśnie dodałem tu kilka twoich komentarzy do pytania, ponieważ zapewniają one dobry kontekst. Dodałem też rzeczy na końcu mojej odpowiedzi :)
Solomon Rutzky
Dziękuję bardzo za odpowiedź! Tak, nazwy i adresy zmieniają się. Jeśli chodzi o wciąż rosnący 20% paradoks, rozumiem, co masz na myśli, ale mówię o początkowym tworzeniu stołu. Klient powie nam, że zacznie wysyłać nam nową tabelę i wyśle ​​przykładowe dane (lub tylko pierwszy zestaw danych produkcyjnych), na które spojrzymy i stworzy tabelę na naszym końcu, aby przechowywać dane. Chcemy, aby nasza tabela obsługiwała przyszły import, a także to, co jest w próbie. Ale niektóre rzędy muszą się wydłużyć, więc je wypełniamy. Pytanie brzmi, ile i czy istnieją wytyczne techniczne?
aristotle2600