czy istnieje przewaga varchar (500) nad varchar (8000)?

91

Przeczytałem o tym na forach MSDN i tutaj i nadal nie jestem pewien. Myślę, że to jest poprawne: Varchar (max) będzie przechowywany jako typ danych tekstowych, więc ma wady. Powiedzmy więc, że Twoje pole będzie niezawodnie zawierać mniej niż 8000 znaków. Podobnie jak pole BusinessName w mojej tabeli bazy danych. W rzeczywistości nazwa firmy będzie prawdopodobnie zawsze składać się z (wyciągając numer z mojego kapelusza) 500 znaków. Wygląda na to, że wiele pól varchar, na które natrafiam, mieści się znacznie poniżej 8 tys. Znaków.

Czy powinienem więc uczynić to pole varchar (500) zamiast varchar (8000)? Z tego, co rozumiem w SQL, nie ma różnicy między tymi dwoma. Aby ułatwić sobie życie, chciałbym zdefiniować wszystkie moje pola varchar jako varchar (8000). Czy to ma jakieś wady?

Powiązane: Rozmiar kolumn varchar (nie czułem, że ten odpowiedział na moje pytanie).

jcollum
źródło
6
Wyobraź sobie, że próbujesz zmieścić nazwę firmy o długości 500 znaków na wizytówce ... :)
OMG Kucyki
2
@OMG Kucyki: za każdym razem, gdy widzę twoją nazwę użytkownika, chichoczę. Co mówiłeś? (
Żartuję
4
@jcollum: SpaceMan Spiff zawsze otrzyma mój głos. To nieprawda - każdy Calvin & Hobbes się nada, a zwłaszcza ci, którzy rzeźbią śnieg. Albo tyranozaur latający na F-14. Ale dygresję ...
OMG Kucyki

Odpowiedzi:

21

Z punktu widzenia przetwarzania nie będzie miało znaczenia użycie varchar (8000) vs varchar (500). To raczej rodzaj „dobrej praktyki”, aby zdefiniować maksymalną długość, jaką pole powinno pomieścić i uczynić varchar taką długością. Jest to coś, co może być pomocne przy sprawdzaniu poprawności danych. Na przykład, nadanie skrótu stanu składającego się z 2 znaków lub kodu pocztowego / pocztowego jako 5 lub 9 znaków. Kiedyś było to ważniejsze rozróżnienie, gdy dane wchodziły w interakcję z innymi systemami lub interfejsami użytkownika, w których długość pola była krytyczna (np. Zestaw danych z płaskim plikiem mainframe), ale obecnie myślę, że jest to bardziej przyzwyczajenie niż cokolwiek innego.

BBlake
źródło
3
Ma sens ... dla rzeczy, które naturalnie mają maksymalną długość. Ale co robisz, gdy maksymalna długość nie jest oczywista? Np. Nazwa firmy.
jcollum
2
W przypadku czegoś takiego, jeśli nie przewiduję żadnego sposobu, aby przewidzieć potencjalny rozmiar, to zwykle
wybieram
4
Wygląda na to, że ma to wpływ na wydajność, nawet w 2017 roku: dba.stackexchange.com/a/162117/1822
a_horse_with_no_name
2
Nowsze odpowiedzi pokazują, że nie koszty: wpływa logika optymalizacji odpowiedź Martina Smitha , a także rozważyć 8K całkowity rozmiar wiersza problemów wymienionych przez gbn i Oliver .
ToolmakerSteve
124

Jednym z przykładów, w którym może to mieć znaczenie, jest to, że może zapobiec optymalizacji wydajności, która pozwala uniknąć dodawania informacji o wersji wierszy do tabel z wyzwalaczami after.

Jest to omówione tutaj w SQL Kiwi

Rzeczywisty rozmiar przechowywanych danych jest nieistotny - liczy się potencjalny rozmiar.

Podobnie w przypadku korzystania z tabel zoptymalizowanych pod kątem pamięci od 2016 r. Możliwe było użycie kolumn LOB lub kombinacji szerokości kolumn, które mogłyby potencjalnie przekroczyć limit inrow, ale z karą.

(Max) kolumny są zawsze przechowywane poza wierszami. W przypadku innych kolumn, jeśli rozmiar wiersza danych w definicji tabeli może przekroczyć 8060 bajtów, SQL Server wypycha największe kolumny o zmiennej długości poza wierszem. Ponownie, nie zależy to od ilości danych, które tam przechowujesz.

Może to mieć duży negatywny wpływ na zużycie pamięci i wydajność

Innym przypadkiem, w którym nadmierne zadeklarowanie szerokości kolumn może mieć duże znaczenie, jest to, czy tabela będzie kiedykolwiek przetwarzana przy użyciu usług SSIS. Pamięć przydzielona dla kolumn o zmiennej długości (innych niż BLOB) jest ustalona dla każdego wiersza w drzewie wykonywania i odpowiada zadeklarowanej maksymalnej długości kolumn, co może prowadzić do nieefektywnego wykorzystania buforów pamięci (przykład) . Chociaż deweloper pakietu SSIS może zadeklarować mniejszy rozmiar kolumny niż źródło, tę analizę najlepiej przeprowadzić z góry i tam wymusić.

W samym silniku SQL Server podobny przypadek jest taki, że podczas obliczania przydziału pamięci do przydzielenia SORToperacji SQL Server zakłada, że varchar(x)kolumny będą średnio zużywać x/2bajty.

Jeśli większość twoich varcharkolumn jest pełniejsza, może to doprowadzić do przeniesienia sortoperacji do tempdb.

W twoim przypadku, jeśli twoje varcharkolumny są zadeklarowane jako 8000bajty, ale w rzeczywistości mają zawartość znacznie mniejszą niż ta, twoje zapytanie otrzyma pamięć, której nie wymaga, co jest oczywiście nieefektywne i może prowadzić do oczekiwania na przydziały pamięci.

Jest to omówione w części 2 prezentacji internetowej dotyczącej warsztatów SQL 1, którą można pobrać stąd lub patrz poniżej.

use tempdb;

CREATE TABLE T(
id INT IDENTITY(1,1) PRIMARY KEY,
number int,
name8000 VARCHAR(8000),
name500 VARCHAR(500))

INSERT INTO  T 
(number,name8000,name500)
SELECT number, name, name /*<--Same contents in both cols*/
FROM master..spt_values

SELECT id,name500
FROM T
ORDER BY number

Zrzut ekranu

SELECT id,name8000
FROM T
ORDER BY number

Zrzut ekranu

Martin Smith
źródło
1
więc jeśli prawie wszystkie moje wartości są 3 lub 4 znakami, nie mogą nigdy przekraczać 4 znaków i chcę uniknąć "przelewania operacji sortowania do tempdb", zadeklaruję moją kolumnę VARCHAR (8) i użyję ograniczenia CHECK, aby wymusić tę kolumnę szerokość nie może przekraczać 4 znaków. Co myślisz?
AK
12
@AlexKuznetsov - W tej sytuacji zadeklarowałbym je jako, char(4)ponieważ i tak jest 2 bajty narzutu na kolumnę zmiennej.
Martin Smith
9

Oprócz najlepszych praktyk (odpowiedź BBlake'a)

  • Otrzymujesz ostrzeżenia o maksymalnym rozmiarze wiersza (8060) bajtów i szerokości indeksu (900 bajtów) z DDL
  • DML umrze, jeśli przekroczysz te limity
  • ANSI PADDING ON jest ustawieniem domyślnym, więc możesz w końcu zapisać całe mnóstwo białych znaków
gbn
źródło
38
Aby wyjaśnić, czym jest ANSI PADDING ON: podczas używania nvarchari varchartypów oznacza to tylko, że końcowe spacje są zachowywane po wstawieniu - a nie, że wartości są dopełniane spacjami do rozmiaru kolumny, jak w chari nchar.
Ben M,
9

Duże kolumny mają pewne wady, które są nieco mniej oczywiste i mogą Cię złapać nieco później:

  • Wszystkie kolumny używane w INDEKSIE - nie mogą przekraczać 900 bajtów
  • Wszystkie kolumny w klauzuli ORDER BY nie mogą przekraczać 8060 bajtów. Jest to trochę trudne do uchwycenia, ponieważ dotyczy to tylko niektórych kolumn. Aby uzyskać szczegółowe informacje, zobacz Przekroczono limit rozmiaru wiersza w programie SQL 2008 R2 )
  • Jeśli łączny rozmiar wiersza przekracza 8060 bajtów, pojawia się „ wyciek strony ” dla tego wiersza. Może to wpłynąć na wydajność (strona jest jednostką alokacji w SQLServer i jest ustalona na 8000 bajtów + trochę narzutu. Przekroczenie tego nie będzie poważne, ale jest zauważalne i powinieneś spróbować tego uniknąć, jeśli możesz)
  • Wiele innych wewnętrznych struktur danych, buforów i wreszcie własne zmienne i zmienne tabel muszą odzwierciedlać te rozmiary. W przypadku nadmiernych rozmiarów nadmierna alokacja pamięci może wpłynąć na wydajność

Zasadniczo staraj się zachować ostrożność przy szerokości kolumny. Jeśli stanie się problemem, możesz go łatwo rozszerzyć, aby dopasować go do potrzeb. Jeśli później zauważysz problemy z pamięcią, późniejsze zmniejszenie szerokiej kolumny może stać się niemożliwe bez utraty danych i nie będziesz wiedział, od czego zacząć.

W swoim przykładzie nazw firm zastanów się, gdzie możesz je wyświetlać. Czy naprawdę jest miejsce na 500 znaków? Jeśli nie, przechowywanie ich jako takich nie ma sensu. http://en.wikipedia.org/wiki/List_of_companies_of_the_United_States zawiera listę niektórych nazw firm, przy czym maksymalna długość to około 50 znaków. Więc użyłbym 100 dla kolumny max. Może bardziej jak 80.

Oliver
źródło
2

Idealnie byłoby, gdybyś chciał zejść mniej niż to, do rozsądnej długości (500 nie ma rozsądnego rozmiaru) i upewnić się, że weryfikacja klienta złapie, gdy dane będą zbyt duże i wyślą użyteczny błąd.

Podczas gdy varchar w rzeczywistości nie rezerwuje miejsca w bazie danych na niewykorzystane miejsce, przypominam sobie, że wersje SQL Server miały problem z wierszami bazy danych, które są szersze niż pewna liczba bajtów (nie pamiętam dokładnej liczby) i faktycznie wyrzucały wszelkie dane nie pasowały. Pewna liczba tych bajtów była zarezerwowana dla elementów wewnętrznych SQL Server.

Otis
źródło
to prawda, to też było o wiele poważniejsze. Ale w dzisiejszych czasach przestrzeń jest naprawdę tania, więc nie wydaje mi się, żeby była to tak duża sprawa do rozważenia, przynajmniej z mojego punktu widzenia.
BBlake,
1
@jcollum: W Twoim przykładzie liczba 500 nie wydaje się być rozsądna dla nazwy firmy.
Otis
1
@BBlake: Niezależnie od kosztu przechowywania, jeśli SQL Server nadal ma ograniczenia dotyczące rozmiaru wiersza, nie ma znaczenia, ile masz miejsca. Możesz przechowywać wszystko w obiektach textblob, ale są pewne operacje SQL, których nie możesz wykonać na obiekcie blob, a które możesz wykonać na varchar.
Otis
2
@Otis: chodzi mi o to: nie ma rzeczywistego ograniczenia wielkości nazwy firmy. Chyba że gdzieś istnieje prawo. Więc w takim przypadku zrobiłbym to pole varchar (8000) i nazwałbym to dniem. Moje myślenie jest takie: Prawdziwe ograniczenie? varchar (x). Brak prawdziwego ograniczenia? varchar (8000).
jcollum
24
Myślałem, że około 30 znaków jest dobre dla nazw miast, dopóki nie zobaczyłem El Pueblo de Nuestra Señora la Reina de los Ángeles del Río de Porciúncula
StuartLC