varchar (max) wszędzie?

81

Czy jest jakiś problem z ustawieniem wszystkich kolumn ciągów w Sql Server 2008 jako varchar (max)? Moimi dopuszczalnymi rozmiarami ciągów zarządza aplikacja. Baza danych powinna po prostu zachować to, co jej daję. Czy osiągnę wydajność, deklarując wszystkie kolumny łańcuchowe jako typu varchar (max) w Sql Server 2008, bez względu na rozmiar danych, które faktycznie do nich trafiają?

BowserKingKoopa
źródło
1
W moim czytaniu brzmi to tak, jakby kolumny Sql Server varchar `` automatycznie dostosowywały się ''. Czy więc kolumna varchar (max), w której maksymalna długość dowolnej podanej wartości wynosi 20, byłaby taka sama jak kolumna varchar (20)?
BowserKingKoopa

Odpowiedzi:

49

Używając w VARCHAR(MAX)zasadzie polecenia SQL Server „przechowuj wartości w tym polu, jak widzisz najlepiej”, SQL Server zdecyduje, czy przechowywać wartości jako zwykłe, VARCHARczy jako LOB (duży obiekt). Ogólnie rzecz biorąc, jeśli przechowywane wartości są mniejsze niż 8 000 bajtów, program SQL Server będzie traktował wartości jako VARCHARtyp zwykły .

Jeżeli wartości zapisane są zbyt duże, wówczas kolumna może rozlać się na stronie w celu stron LOB, dokładnie tak samo jak w przypadku innych typów LOB ( text, ntexti image) - jeśli tak się stanie wtedy dodatkowe Odczyty są wymagane do odczytywania danych zapisanych w dodatkowe strony (tzn. występująca wydajność), jednak dzieje się tak tylko wtedy, gdy zapisane wartości są zbyt duże .

W rzeczywistości w SQL Server 2008 lub nowszym dane mogą przelewać się na dodatkowe strony, nawet w przypadku typów danych o stałej długości (np. VARCHAR(3,000)), Jednak strony te nazywane są stronami danych przepełnienia wierszy i są traktowane nieco inaczej.

Krótka wersja: z punktu widzenia przechowywania nie ma wady używania VARCHAR(MAX)przez VARCHAR(N)niektórych N.

(Zwróć uwagę, że dotyczy to również innych typów pól o zmiennej długości NVARCHARi VARBINARY)

Do Twojej wiadomości - nie możesz tworzyć indeksów w VARCHAR(MAX)kolumnach

Justin
źródło
Może to dotyczyć tylko pól dopuszczających wartość null. Każda niezerowa kolumna varchar (max) lub nvarchar (max) wymaga 24 bajtów dodatkowej stałej alokacji. docs.microsoft.com/en-us/sql/t-sql/data-types/…
Liazy
34

Indeksy nie mogą mieć więcej niż 900 bajtów na jeden. Więc prawdopodobnie nigdy nie możesz utworzyć indeksu. Jeśli twoje dane mają mniej niż 900 bajtów, użyj varchar (900).

To jest jedna wada: ponieważ daje

  • naprawdę słaba wydajność wyszukiwania
  • brak unikalnych ograniczeń
gbn
źródło
Ale co, jeśli kolumna varchar (max) nie zawiera żadnych wartości większych niż 900 bajtów? Czy to będzie indeksowane? Jestem zdezorientowany, ponieważ wiele z tego, co czytam, sprawia, że ​​typy kolumn varchar brzmią tak, jakby automatycznie dostosowywały się do maksymalnego rozmiaru po wprowadzeniu danych. Byłoby to idealne do tego, czego chcę, ponieważ to aplikacja powinna decydować o maksimum, a nie baza danych.
BowserKingKoopa,
3
Otrzymasz ostrzeżenie podczas tworzenia indeksu i błąd podczas próby wstawienia> 900. Ale jeśli twoje dane są zawsze <900, dlaczego nie użyć 900? Tak, są one jednak przechowywane jako ciągi o zmiennej długości.
gbn
8
Nie wiem, czy moje dane są zawsze <900. To problem logiki biznesowej. Jeśli ta reguła się zmieni, powinienem to zmienić w logice biznesowej. Nie powinienem też zmieniać bazy danych. W każdym razie to mój cel. Aby sprawdzić, czy uda mi się odejść od troski o rozmiary ciągów z bazy danych bez zauważalnego spadku wydajności.
BowserKingKoopa,
2
Jak często warto indeksować długą kolumnę tekstu? Czy warto byłoby nawet zindeksować coś w rodzaju kolumny varchar (200)? W końcu sam indeks byłby nieefektywny. Konieczność wyszukiwania długich „dokładnych dopasowań” wydaje się mało prawdopodobna. Wyszukiwanie wzorców przyniosłoby korzyści tylko wtedy, gdy znany jest początek wzorca.
Rozczarowany
9

Simon Sabin napisał na ten temat post jakiś czas temu. Nie mam teraz czasu, aby go teraz złapać, ale powinieneś go poszukać, ponieważ dochodzi do wniosku, że nie powinieneś domyślnie używać varchar (max).

Edytowano: Simon ma kilka postów o varchar (max). Linki w komentarzach poniżej pokazują to całkiem ładnie. Myślę, że najbardziej znaczący jest http://sqlblogcasts.com/blogs/simons/archive/2009/07/11/String-concatenation-with-max-types-stops-plan-caching.aspx , który mówi o efekcie varchar (max) na buforowanie planu. Ogólna zasada to ostrożność. Jeśli nie potrzebujesz max, nie używaj max - jeśli potrzebujesz więcej niż 8000 znaków, to na pewno ... idź do tego.

Rob Farley
źródło
Pierwszy. Przez OMG Kucyki.
Rob Farley,
Przepraszam, że nie miałem czasu, aby znaleźć rzeczywisty link, właśnie miałem wejść na spotkanie, kiedy chciałem odpalić odpowiedź.
Rob Farley,
1
A co ważniejsze, ten: sqlblogcasts.com/blogs/simons/archive/2009/07/11/…
Rob Farley
6

W przypadku tego pytania kilka punktów, których nie widzę, zostało wspomnianych.

  1. W wersji 2005/2008/2008 R2, jeśli kolumna LOB jest uwzględniona w indeksie, spowoduje to zablokowanie odbudowy indeksu online.
  2. W 2012 r. Ograniczenie odbudowy indeksu w trybie online zostało zniesione, ale kolumny LOB nie mogą uczestniczyć w nowej funkcji Dodawanie kolumn NOT NULL jako operacji online .
  3. Blokady można wyjąć dłużej w wierszach zawierających kolumny tego typu danych. ( więcej )

Moja odpowiedź dotyczy kilku innych powodów, dlaczego nie varchar(8000)wszędzie .

  1. Twoje zapytania mogą kończyć się żądaniem ogromnych przydziałów pamięci, które nie są uzasadnione wielkością danych.
  2. W tabeli z wyzwalaczami może zapobiec optymalizacji, w której tagi wersjonowania nie są dodawane.
Martin Smith
źródło
5

Podobne pytanie zadałem wcześniej. otrzymałem kilka interesujących odpowiedzi. sprawdź to tutaj Była jedna witryna, w której facet mówił o szkodach związanych z używaniem szerokich kolumn, jednak jeśli twoje dane są ograniczone w aplikacji, moje testy to obaliły. Fakt, że nie możesz tworzyć indeksów na kolumnach, oznacza, że ​​nie używałbym ich przez cały czas (osobiście nie używałbym ich w ogóle, ale pod tym względem jestem trochę purystą). Jeśli jednak wiesz, że nie ma w nich dużo przechowywanych, nie sądzę, że są takie złe. Jeśli posortujesz na kolumnach zestaw rekordów z wartością varchar (max) (lub dowolna szeroka kolumna będąca char lub varchar), możesz ponieść straty wydajności. można je rozwiązać (jeśli jest to wymagane) za pomocą indeksów, ale nie można umieścić indeksów w varchar (max). Jeśli chcesz zabezpieczyć swoje kolumny w przyszłości, możesz po prostu postawić je na coś rozsądnego. np. kolumna z nazwiskiem ma 255 znaków zamiast max ...

Ze stratą
źródło
2

Jest jeszcze jeden powód, dla którego należy unikać używania varchar (max) we wszystkich kolumnach. Z tego samego powodu używamy ograniczeń sprawdzających (aby uniknąć wypełniania tabel śmieciami spowodowanymi przez błędne oprogramowanie lub wpisy użytkowników), chcielibyśmy zabezpieczyć się przed jakimkolwiek błędnym procesem, który dodaje znacznie więcej danych niż zamierzano. Na przykład, jeśli ktoś lub coś próbowałoby dodać 3000 bajtów do pola City, wiedzielibyśmy na pewno, że coś jest nie tak i chcielibyśmy zatrzymać proces w martwym punkcie, aby debugować go w jak najwcześniejszym momencie. Wiedzielibyśmy również, że 3000-bajtowa nazwa miasta nie mogłaby być prawidłowa i zepsułaby raporty i tym podobne, gdybyśmy spróbowali jej użyć.

Larry Ness
źródło
1

Najlepiej byłoby zezwalać tylko na to, czego potrzebujesz. Oznacza to, że jeśli masz pewność, że określona kolumna (powiedzmy, kolumna z nazwą użytkownika) nigdy nie będzie dłuższa niż 20 znaków, użycie VARCHAR (20) w porównaniu z VARCHAR (MAX) pozwala bazie danych zoptymalizować zapytania i struktury danych.

Z MSDN: http://msdn.microsoft.com/en-us/library/ms176089.aspx

Variable-length, non-Unicode character data. n can be a value from 1 through 8,000. max indicates that the maximum storage size is 2^31-1 bytes.

Czy naprawdę zamierzasz kiedykolwiek zbliżyć się do 2 ^ 31-1 bajtów dla tych kolumn?

leepowers
źródło
3
Nie sądzę, by trafne było określanie tego jako „przydzielania”. Baza danych z pewnością nie rezerwuje nigdzie 2 ^ 31-1 bajtów.
Scott Stafford
1
„kolumna nazwy użytkownika […] nigdy nie będzie dłuższa niż 20 znaków” - Dobrze, aż pewnego dnia klient zdecyduje, że musi być dłuższy. Wszyscy tam byliśmy. :)
Steve Smith