Używanie MAX tekstu lub dokładniejszego, mniejszego typu

22

Ktoś sprawdzał mój kod DDL do tworzenia tabel i zasugerował, gdy zobaczył, że używam VARCHAR(256)pól do tekstu, spodziewam się, że będzie dość mały, jak imię lub cokolwiek innego, że powinienem zawsze używać VARCHAR(MAX)i łączyć. Dlaczego używać niczego innego niż varchar (maks. ) . Przeczytałem to, ale wydawało się to przestarzałe, ponieważ koncentrowało się na 2005 r., I nie wydawało się, aby stanowiło prawdziwe uzasadnienie dla przydzielenia potencjalnie do 2 GB na wiersz na wszystkie pola tekstowe.

Z punktu widzenia wydajności, pamięci masowej itp., Jak należy decydować, czy użyć VARCHAR(MAX)lub mniejszego bardziej konkretnego typu dla nowoczesnych wersji SQL Server? (np. 2008, 2012, 2014)

Phrancis
źródło

Odpowiedzi:

31

Czy zawsze powinienem używać (n)varchar(max)do kolumn tekstowych?

Nie.

W przypadku SQL Server maxtypy danych należy określać tylko wtedy, gdy nie ma alternatywy. Zamiast tego należy wybrać prawidłowy typ podstawowy ( varcharlub nvarchar) i określić jawną maksymalną długość odpowiednią dla przechowywanych danych.

Pamięć fizyczna jest identyczna bez względu na to, czy kolumna jest wpisana jako varchar(n)czy varchar(max), więc nie jest to problemem.

Powody, dla których nie(n)varchar(max) wszędzie wybierasz, dotyczą głównie funkcji, jakości planu i wydajności.

Wyczerpująca lista prawdopodobnie nie jest praktyczna, ale między innymi maxkolumny:

cechy

  • Wymagaj osobnego ograniczenia w celu wymuszenia maksymalnej długości
  • Nie może być kluczem w indeksie (więc nie ma też unikalnych ograniczeń)
  • Może uniemożliwić DDL online (w tym przebudowy indeksu i dodanie nowej kolumny innej niż null)
  • Na ogół nie są obsługiwane dla „nowszych” funkcji, np. Magazynu kolumn
  • Bardziej szczegółowe funkcje i ograniczenia można znaleźć w dokumentacji produktu. Ogólny wzorzec jest taki, że istnieją dziwne ograniczenia i ograniczenia maxdotyczące typów danych. Nie wszystkie ograniczenia i skutki uboczne są udokumentowane.

Wydajność

  • Wymagaj specjalnej obsługi w silniku wykonywania, aby uwzględnić potencjalnie bardzo duży rozmiar. Zazwyczaj wymaga to użycia mniej wydajnej ścieżki kodu z interfejsem przesyłania strumieniowego
  • Może mieć podobne nieoczekiwane konsekwencje dla zewnętrznego kodu (i innych składników SQL Server, takich jak SSIS), które muszą być również przygotowane do obsługi danych o wielkości do 2 GB
  • Przyjmuje się, że mają 4000 bajtów szerokości w obliczeniach przyznania pamięci. Może to prowadzić do nadmiernej rezerwacji pamięci, co ogranicza współbieżność i wypycha cenne strony indeksu i danych z pamięci podręcznej
  • Wyłącz kilka ważnych optymalizacji wydajności
  • Może wydłużyć czas blokady
  • Może uniemożliwić optymalizatorowi wybranie (niedynamicznego) planu wyszukiwania
  • Zapobiegaj popychaniu filtrów do skanów i szuka jako pozostałości
  • Może zwiększać ciśnienie i rywalizację tempdb (zależnie od wersji), ponieważ zmienne i parametry mogą być również wpisywane w maxcelu dopasowania definicji kolumn

Podsumowując, istnieje tak wiele subtelnych (i niepożądanych) skutków ubocznych niepotrzebnego używania maxspecyfikatora, że ​​nie ma sensu tego robić. Drobna „wygoda” korzystania z jednej deklaracji nie stanowi żadnej rekompensaty.

Oceń każdy typ w kontekście, użyj prawidłowego typu podstawowego ( varcharlub nvarchar) i rozsądnej wyraźnej długości.

Dalsza lektura:

Paul White mówi GoFundMonica
źródło
8

Będzie to brzmiało jak odpowiedź paranoika, ale nie tylko kwestie przechowywania i wydajności.

Sama baza danych nie kontroluje swoich klientów i nie można zakładać, że klienci zawsze bezpiecznie wstawiają dane wejściowe użytkownika - nawet jeśli baza danych jest zaprojektowana do użytku tylko z aplikacją .net, która używa Entity Framework do kapsułkowania transakcji i zapewnienia sparametryzowanych zapytań są systematycznie używane, nie możesz wiedzieć , że zawsze tak będzie.

Nie wiedziałbym dokładnie, jak to zrobić, ale poprzez utworzenie wszystkich pól tekstowych varchar(max), jeśli klient ma problemy z tabelami Bobby i / lub parametry Twoich procedur przechowywanych varchar(max), to ułatwisz atakującemu wymyślenie poprawna, ale sprytnie zła wartość parametru, która może robić rzeczy, których klienci nie powinni robić - cokolwiek to jest.

Ograniczając długość do tego, czego naprawdę potrzebujesz, nie chronisz się przed tymi sprytnymi atakami (nawet nie jestem pewien, jak to się naprawdę nazywa, po prostu pamiętam o tym jakiś czas temu), ale nie mówisz „ śmiało, spróbuj dać mi skrypt o pojemności 2 GB, aby uruchomić „albo.

Mathieu Guindon
źródło
To, co się nazywa, to prawdopodobnie „wstrzyknięcie” (dokładniej „wstrzyknięcie SQL”).
Andriy M,
@AndriyM tak, z jakiegoś powodu myślałem o atakach obcięcia SQL (MS zdaje się usunąć link, który dodałem do zakładek), ale to w zasadzie wykorzystuje varchar(not-max)parametry, więc trochę utknąłem tutaj w ustach. Ale tak, zastrzyk SQL miałby tu zastosowanie. Być może powinienem nieco sformułować tę odpowiedź.
Mathieu Guindon,