Czy są jakieś wady korzystania z nvarchar (MAX)?

342

Czy w SQL Server 2005 występują jakieś wady tworzenia wszystkich pól znakowych nvarchar (MAX) zamiast jawnego podawania długości, np. Nvarchar (255)? (Poza oczywistym, że nie jesteś w stanie ograniczyć długości pola na poziomie bazy danych)

stucampbell
źródło
1
Po prostu nie rozumiem, dlaczego chcesz pozwolić komuś wejść w imię ponad 8000 znaków.
DForck42
2
Tę samą logikę można zastosować do języków programowania. Dlaczego nie wrócić do starego wariantu VB6 dla wszystkich naszych danych? Nie sądzę, aby posiadanie czeków i sald w więcej niż jednym miejscu było koniecznie złe.
Matt Spradley,
1
Sprawdź to: stackoverflow.com/questions/2009694/…
Akira Yamamoto,
10
Twoja aktualizacja powinna być własną odpowiedzią na to pytanie.
Johann
odpowiedź na pytanie została przeniesiona do właściwej odpowiedzi, ponieważ autor tego nie zrobił. stackoverflow.com/a/35177895/10245 Myślę, że 7 lat to wystarczający czas :-)
Tim Abell

Odpowiedzi:

153

To samo pytanie zadano na forach MSDN:

Z oryginalnego postu (tam więcej informacji):

Gdy przechowujesz dane w kolumnie VARCHAR (N), wartości są fizycznie przechowywane w ten sam sposób. Ale kiedy przechowujesz je w kolumnie VARCHAR (MAX), za ekranem dane są traktowane jako wartość TEXT. Dlatego w przypadku wartości VARCHAR (MAX) konieczne jest dodatkowe przetwarzanie. (tylko jeśli rozmiar przekracza 8000)

VARCHAR (MAX) lub NVARCHAR (MAX) jest uważany za „typ dużej wartości”. Typy dużych wartości są zwykle przechowywane „poza wierszem”. Oznacza to, że wiersz danych będzie miał wskaźnik do innej lokalizacji, w której przechowywana jest „duża wartość” ...

David Kreps
źródło
2
Czy zatem powinno być pytanie, czy istnieje różnica między używaniem N / VARCHAR (MAX) i N / TEXT?
Unsliced
18
Jeśli dobrze pamiętam, czy nie są one przechowywane poza wierszem tylko wtedy, gdy rozmiar przekracza 8k?
Sam Schutte
79
Przeczytałem odpowiedź jako „nie, nie ma wady korzystania z N/VARCHAR(MAX)”, ponieważ istnieje dodatkowe przetwarzanie „tylko wtedy, gdy rozmiar przekracza 8000”. W związku z tym ponosisz koszty tylko wtedy , gdy jest to konieczne , a twoja baza danych jest mniej restrykcyjna . Czy źle to czytam? Wygląda na to, że prawie zawsze chciałbyś N/VARCHAR(MAX)zamiast N/VARCHAR(1-8000)...
Kent Boogaart
1
Martwy link powyżej - działający link do pytania na MSDN to social.msdn.microsoft.com/Forums/en-US/sqlgetstarted/thread/…
Jagd
68
Niestety ta odpowiedź ma wiele problemów. Sprawia, że ​​granica 8k wydaje się być liczbą magiczną, nie jest prawdą, wartość jest wypychana z rzędu na podstawie większej liczby czynników, w tym sp_tableoptions: msdn.microsoft.com/en-us/library/ms173530.aspx . Typy VARCHAR (255) można również wypchnąć z wiersza, wspomniany „narzut” może być dokładnie taki sam dla MAX i 255. Porównuje typy MAX z typami TEKSTOWYMI, gdy są one różne w miarę ich uzyskiwania (całkowicie inny interfejs API do manipulowania, inne miejsce do przechowywania itp.). Nie wspomina o rzeczywistych różnicach: brak indeksu, brak operacji online na typach MAX
Remus Rusanu
50

To uczciwe pytanie, a on stwierdził poza oczywistym…

Wady mogą obejmować:

Wpływ na wydajność Optymalizator kwerend wykorzystuje rozmiar pola do ustalenia najbardziej skutecznego planu egzekwowania

„1. Przydział miejsca w rozszerzeniach i stronach bazy danych jest elastyczny. Dlatego dodając informacje do pola za pomocą aktualizacji, baza danych musiałaby utworzyć wskaźnik, jeśli nowe dane są dłuższe niż poprzednio wstawione. To pliki bazy danych stać się rozdrobnione = niższa wydajność prawie we wszystkim, od indeksu do usuwania, aktualizacji i wstawiania. ” http://sqlblogcasts.com/blogs/simons/archive/2006/02/28/Why-use-anything-but-varchar_2800_max_2900_.aspx

Wpływ na integrację - inne systemy mają trudności z integracją z bazą danych Nieprzewidziany wzrost danych Możliwe problemy z bezpieczeństwem, np. Można zawiesić system, zajmując całe miejsce na dysku

Dobry artykuł tutaj: http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1098157,00.html

alexmac
źródło
4
+1 Za wpływ na integrację i bezpieczeństwo. Są to oryginalne podejście do rozważenia, gdy większość innych odpowiedzi mówi o wydajności. W związku z implikacjami związanymi z integracją wszelkie narzędzia (takie jak autorzy raportów lub projektanci formularzy), które wykorzystują metadane do zapewnienia rozsądnych domyślnych rozmiarów kontroli, wymagałyby znacznie więcej pracy, gdyby wszystkie kolumny były varchar(max).
Rozczarowany
Integracja z bazą danych jest najbardziej absurdalną rzeczą, co wiem. Jeśli jest to tylko import, możesz raz sprawdzić dane za pomocą funkcji LEN.
Maxim,
30

Na podstawie linku podanego w zaakceptowanej odpowiedzi wydaje się, że:

  1. 100 znaków przechowywanych w nvarchar(MAX)polu będzie przechowywanych nie inaczej niż 100 znaków w nvarchar(100)polu - dane będą przechowywane w wierszu i nie będziesz mieć narzutu związanego z odczytywaniem i zapisywaniem danych „poza wierszem”. Więc nie martw się.

  2. Jeśli rozmiar jest większy niż 4000, dane byłyby automatycznie zapisywane „poza wierszem”, co byś chciał. Nie martw się też.

Jednak...

  1. Nie można utworzyć indeksu w nvarchar(MAX)kolumnie. Możesz użyć indeksowania pełnotekstowego, ale nie można utworzyć indeksu w kolumnie, aby poprawić wydajność zapytania. Dla mnie to uszczelnia umowę ... zdecydowanie wadą jest zawsze używanie nvarchar (MAX).

Wniosek:

Jeśli chcesz mieć coś w rodzaju „uniwersalnej długości ciągu” w całej bazie danych, która może być indeksowana i która nie będzie marnować miejsca i czasu dostępu, możesz użyć nvarchar(4000).

Tim Abell
źródło
1
fyi była to zmiana dodana do pierwotnego pytania, która powinna była zostać opublikowana jako odpowiedź
Tim Abell
1
Dzięki, dla mnie to jest ostateczna odpowiedź. Zadałem sobie to samo - dlaczego nie korzystać nvarchar(max)cały czas - jak stringw C #? - ale punkt 3) (problem z indeksem) daje odpowiedź.
SQL Police
1
Dodano edycję. Jako rodzaj „uniwersalnej długości ciągu”, zawsze możesz użyćnvarchar(4000)
SQL Police
@SQLGeorge Zobacz tę doskonałą odpowiedź Martina Smitha na temat wpływu na wydajność zapytania deklarowania kolumn szerszych niż kiedykolwiek
billinkc
@billinkc Dzięki, to świetny artykuł. OK, więc rozmiar rzeczywiście wpływa na wydajność. Zmienię odpowiedź ponownie.
SQL Police
28

Czasami chcesz, aby typ danych wymusił pewien sens na danych w nim zawartych.

Powiedzmy na przykład, że masz kolumnę, która tak naprawdę nie powinna być dłuższa niż, powiedzmy, 20 znaków. Jeśli zdefiniujesz tę kolumnę jako VARCHAR (MAX), niektóre nieuczciwe aplikacje mogą wstawić do niej długi ciąg znaków i nigdy byś się nie dowiedział, ani nie mógł w żaden sposób temu zapobiec.

Następnym razem, gdy aplikacja użyje tego ciągu, przy założeniu, że długość łańcucha jest skromna i rozsądna dla reprezentowanej przez niego domeny, wystąpi nieprzewidziany i mylący wynik.

Bill Karwin
źródło
9
Zgadzam się z tym i niektórymi innymi komentarzami, ale nadal twierdzę, że to poziom odpowiedzialności biznesu. Zanim osiągnie poziom bazy danych, powinien zrobić salut i zapisać wartość, bez względu na to, jak absurdalnie długo to trwa. Myślę, że tak naprawdę tu chodzi o to, że myślę o 90% przypadków, gdy deweloper określa varchar (255), jego intencją nie jest tak naprawdę 255 znaków, ale pewna nieokreślona średnia długość. Biorąc pod uwagę kompromis między nieuzasadnionymi dużymi wartościami w mojej bazie danych i nieprzewidzianymi wyjątkami, wezmę duże wartości.
Chris B. Behrens
4
Jeśli określają VARCHAR (255), aby wskazać nieznaną długość, to ich wina, że ​​nie zbadali właściwie, co projektują. Rozwiązaniem jest, aby programista wykonał swoje zadanie, a nie baza danych, aby umożliwić nieuzasadnione wartości.
Tom H
10
nie pomocne dla autora. wyraźnie wykluczył to pytanie, na które udzieliłeś odpowiedzi.
usr
6
@ Chris B Behrens: Nie zgadzam się; schemat bazy danych jest częścią logiki biznesowej. Wybór tabel, relacji, pól i typów danych opiera się na logice biznesowej - warto stosować RDBMS do egzekwowania reguł tej logiki biznesowej. Z jednego powodu bardzo rzadko zdarza się, że tylko jedna warstwa aplikacji uzyskuje dostęp do bazy danych; na przykład możesz mieć narzędzia do importowania i wyodrębniania danych, które omijają główny poziom biznesowy, co oznacza, że ​​naprawdę potrzebujesz bazy danych do egzekwowania reguł.
Vince Bowdren
1
Jeśli nie potrzebujesz lub rzeczywiście chcesz przechowywać długie łańcuchy, lepiej wymusić sens danych. Na przykład, jeśli przechowujesz pole PostCode, czy pozwoliłbyś komuś wprowadzić setki lub tysiące znaków, gdy powinno to być maksymalnie 10 powiedz. - maksymalny rozmiar powinien być sprawdzony na wszystkich poziomach, kliencie, poziomie biznesowym ORAZ bazie danych. Jeśli używasz metody Najpierw model, takiej jak w C # i Entity Framework, możesz zdefiniować maksymalny rozmiar w modelu i zastosować go do bazy danych, logiki biznesowej i sprawdzania poprawności klienta (podobnie jak sprawdzanie poprawności jquery). Używaj nvarchar (maks.) Tylko, jeśli jest to naprawdę wymagane
Peter Kerr 10'17
21

Sprawdziłem kilka artykułów i znalazłem przydatny skrypt testowy z tego: http://www.sqlservercentral.com/Forums/Topic1480639-1292-1.aspx Następnie zmieniłem go, aby porównać NVARCHAR (10) vs NVARCHAR (4000) vs NVARCHAR (MAX ) i nie znajduję różnicy prędkości przy użyciu określonych liczb, ale przy użyciu MAX. Możesz samemu przetestować. Mam nadzieję, że to pomoże.

SET NOCOUNT ON;

--===== Test Variable Assignment 1,000,000 times using NVARCHAR(10)
DECLARE @SomeString NVARCHAR(10),
        @StartTime DATETIME;
--=====         
 SELECT @startTime = GETDATE();
 SELECT TOP 1000000
        @SomeString = 'ABC'
   FROM master.sys.all_columns ac1,
        master.sys.all_columns ac2;
 SELECT testTime='10', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(4000)
DECLARE @SomeString NVARCHAR(4000),
        @StartTime DATETIME;
 SELECT @startTime = GETDATE();
 SELECT TOP 1000000
        @SomeString = 'ABC'
   FROM master.sys.all_columns ac1,
        master.sys.all_columns ac2;
 SELECT testTime='4000', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(MAX)
DECLARE @SomeString NVARCHAR(MAX),
        @StartTime DATETIME;
 SELECT @startTime = GETDATE();
 SELECT TOP 1000000
        @SomeString = 'ABC'
   FROM master.sys.all_columns ac1,
        master.sys.all_columns ac2;
 SELECT testTime='MAX', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
QMaster
źródło
4
To interesujące. Na moim pudełku wydaje się, że MAX jest 4x wolniejszy.
stucampbell
4
Nowe wyniki w SQL Server 2012: 10 jest dwa razy wolniejsze niż 4k, a MAX jest 5,5 razy wolniejsze niż 4k.
cassandrad
1
Większość czasu to niejawna obsada z varchar na nvarchar (max). Spróbuj tego: DECLARE \ @SomeString NVARCHAR (MAX), \ @abc NVARCHAR (max) = N'ABC ', \ @StartTime DATETIME; SELECT @startTime = GETDATE (); WYBIERZ TOP 1000000 \ @SomeString = \ @abc z master.sys.all_columns ac1, master.sys.all_columns ac2; WYBIERZ testTime = „MAX”, Duration = DATEDIFF (ms, \ @ StartTime, GETDATE ()); Musiałem wstawić \ przed zmiennymi, aby opublikować.
Kvasi
4
SQL Server 2014 na dysku SSD: 150, 156, 716 (10, 4000, MAX).
Maxim
2
Dziękujemy za dodanie prawdziwych liczb do tej dyskusji. Często zapominamy, że zbudowanie skrzynki testowej jest najszybszym sposobem na wgląd.
David C
13

Potraktuj to jako kolejny poziom bezpieczeństwa. Możesz zaprojektować swoją tabelę bez relacji klucza obcego - całkowicie poprawne - i zapewnić istnienie powiązanych jednostek całkowicie na warstwie biznesowej. Jednak klucze obce są uważane za dobrą praktykę projektowania, ponieważ dodają kolejny poziom ograniczenia na wypadek, gdyby coś poszło nie tak w warstwie biznesowej. To samo dotyczy ograniczenia wielkości pola i niestosowania varchar MAX.

Alex
źródło
8

Powodem, dla którego NIE należy używać pól maksymalnych lub tekstowych, jest to, że nie można wykonać przebudowy indeksu online, tj. ODBUDUJ ONLINE = WŁĄCZONY, nawet przy SQL Server Enterprise Edition.

Nick Kavadias
źródło
1
To samo ograniczenie obowiązuje dla typu pola TEKST, więc nadal należy używać VARCHAR (MAX) zamiast TEXT.
Will Shaver,
z tego powodu nie mogliśmy odbudować naszego indeksu klastrowego. kosztowało nas dużo miejsca na dysku, zanim mogliśmy wyodrębnić kolumnę do własnego stołu (nie było nas stać na zablokowanie stołu na dłużej niż 7 sekund)
Choco Smith
4

Jedynym problemem było to, że znalazłem rozwijamy nasze aplikacje na SQL Server 2005, a w jednym przypadku mamy do wspierania SQL Server 2000. Właśnie dowiedziałem się, w bolesny sposób , że SQL Server 2000 nie lubi opcji MAX dla varchar lub nvarchar.

mattruma
źródło
2
Dlaczego więc nie rozwinąć według najniższego wspólnego mianownika?
binki
4

Zły pomysł, gdy wiesz, że pole będzie w ustawionym zakresie - na przykład od 5 do 10 znaków. Myślę, że użyłbym maksimum tylko wtedy, gdy nie byłem pewien, jaka będzie długość. Na przykład numer telefonu nigdy nie byłby dłuższy niż pewna liczba znaków.

Czy możesz szczerze powiedzieć, że nie masz pewności co do wymagań dotyczących przybliżonej długości każdego pola w tabeli?

Rozumiem twój punkt widzenia - są pewne pola, które z pewnością rozważę użycie varchar (max).

Co ciekawe, dokumenty MSDN całkiem dobrze to podsumowują:

Użyj varchar, gdy rozmiary wpisów danych kolumn znacznie się różnią. Użyj varchar (maks.), Gdy rozmiary wpisów danych w kolumnach znacznie się różnią, a rozmiar może przekraczać 8 000 bajtów.

Tutaj jest ciekawa dyskusja na ten temat .

RichardOD
źródło
2
W przypadku takich rzeczy jak numery telefonów, byłbym o wiele bardziej zadowolony z używania pola char zamiast varchar. Tak długo, jak utrzymujesz standard w pamięci i nie musisz się martwić o numery telefonów z różnych krajów, nigdy nie powinieneś potrzebować zmiennej zmiennej na coś takiego jak numer telefonu (10 bez formatowania) lub kod pocztowy (5 lub 9-10, jeśli dodasz cztery ostatnie cyfry) itp.
TheTXI
Miałem na myśli numery telefonów, które mogą różnić się długością. Być może powinienem umieścić to w odpowiedzi. Wszystko o ustalonej długości użyłbym pola char.
RichardOD
A może powinienem powiedzieć w moim komentarzu nchar lub char. :-)
RichardOD
2
Liczba znaków w numerze telefonu jest w zasadzie wymogiem biznesowym. Jeśli będziesz musiał przechowywać międzynarodowy standardowy kod wraz z numerem, może on być większy niż 10. Lub, w niektórych częściach świata, może być więcej niż 10 cyfr dla numeru telefonu. Wyobraź sobie przypadek przejścia z IPV4 na IPV6. Nikt nie twierdziłby, że potrzebujemy więcej niż 12 cyfr w starych dobrych czasach IPV4. Może się nie udać, jeśli IPV6 stanie się dominujący. To znowu zmiana reguły biznesowej na przestrzeni czasu. Jak już powiedziano, zmiana jest jedyną stałą rzeczą, jakiej możemy się spodziewać :)
pencillate
2
Zachowaj ostrożność, zakładając, że wiesz, ile znaków może znajdować się w polu numeru telefonu lub jakie to będą znaki. O ile system nie użyje tych danych do faktycznego wybrania numeru (w takim przypadku musisz ściśle przestrzegać formatów), użytkownik może legalnie umieścić nieoczekiwanie długie ciągi znaków, np. „0123 456 78910 poprosić o odbiór rozszerzenia 45, a następnie przesłać je do Jamesa”.
Vince Bowdren,
4

Zadaniem bazy danych jest przechowywanie danych, aby mogły z nich korzystać przedsiębiorstwa. Częścią uczynienia tych danych użytecznymi jest zapewnienie, że mają one sens. Umożliwienie komuś wpisania nieograniczonej liczby znaków dla imienia nie zapewnia znaczących danych.

Wbudowanie tych ograniczeń w warstwę biznesową jest dobrym pomysłem, ale nie gwarantuje to, że baza danych pozostanie nienaruszona. Jedynym sposobem zagwarantowania, że ​​reguły dotyczące danych nie zostaną naruszone, jest wymuszenie ich na najniższym możliwym poziomie w bazie danych.

Tom H.
źródło
6
IMO ograniczenia długości danych opierają się wyłącznie na regułach biznesowych, które mogą się zmieniać w miarę upływu czasu wraz ze wzrostem aplikacji. Zmiana reguł biznesowych w logice biznesowej jest łatwiejsza niż na poziomie db. Myślę więc, że db powinien być wystarczająco elastyczny i nie powinien być związany z regułami biznesowymi, takimi jak maksymalna dozwolona długość imienia, która jest bardzo zależna od części świata, w której mieszka użytkownik.
pencillate
3

Jednym z problemów jest to, że jeśli musisz pracować z wieloma wersjami SQL Server, MAX nie zawsze będzie działać. Więc jeśli pracujesz ze starszymi DB lub inną sytuacją, która dotyczy wielu wersji, lepiej bądź bardzo ostrożny.

TheTXI
źródło
Myślę, że niewypowiedzianym założeniem PO jest to, że ma on do czynienia całkowicie z instancjami 2005+ i że jego aplikacje nie będą musiały działać w wersjach 2000 (a nawet niższych). Całkowicie się z tobą zgadzam, jeśli zachodzi potrzeba obsługi starszych wersji!
John Rudy,
John Rudy: Wyobrażam sobie, że tak jest, po prostu wiem, że sam wpadłem na te przeszkody, kiedy nie myślałem, że zamierzam.
TheTXI
W rzeczywistości jest to nadal powszechny problem związany z nowoczesnymi rozwiązaniami ze względu na SQL CE 4, który nie obsługuje typów kolumn MAX, więc interoperacyjność jest kłopotliwa.
JohnC,
3

Jak wspomniano powyżej, jest to przede wszystkim kompromis między pamięcią masową a wydajnością. Przynajmniej w większości przypadków.

Jest jednak co najmniej jeden inny czynnik, który należy wziąć pod uwagę przy wyborze n / varchar (Max) zamiast n / varchar (n). Czy dane będą indeksowane (np. Nazwisko)? Ponieważ definicja MAX jest uważana za LOB, wszystko zdefiniowane jako MAX nie jest dostępne do indeksowania. i bez indeksu każde wyszukiwanie obejmujące dane jako predykat w klauzuli WHERE będzie zmuszone do skanowania pełnego stołu, co jest najgorszą wydajnością, jaką można uzyskać dla wyszukiwania danych.

Harry Cooper
źródło
2

1) Serwer SQL będzie musiał zużywać więcej zasobów (przydzielona pamięć i czas procesora) podczas pracy z nvarchar (max) vs nvarchar (n), gdzie n jest liczbą specyficzną dla tego pola.

2) Co to oznacza w odniesieniu do wydajności?

W SQL Server 2005 przeszukałem 13 000 wierszy danych z tabeli zawierającej 15 kolumn nvarchar (max). Wielokrotnie mierzyłem czas zapytań, a następnie zmieniałem kolumny na nvarchar (255) lub mniej.

Kwerendy przed optymalizacją uśredniono na 2,0858 sekund. Zapytania po zmianie powróciły średnio w 1,90 sekundy. To było około 184 milisekund ulepszenia podstawowego zapytania select *. To poprawa o 8,8%.

3) Moje wyniki są zbieżne z kilkoma innymi artykułami wskazującymi na różnicę w wydajności. W zależności od bazy danych i zapytania odsetek ulepszeń może się różnić. Jeśli nie masz wielu równoczesnych użytkowników lub bardzo wielu rekordów, różnica w wydajności nie będzie dla ciebie problemem. Różnica w wydajności wzrośnie jednak wraz ze wzrostem liczby rekordów i jednoczesnych użytkowników.

WWC
źródło
1

Miałem udf, który wypełniał napisy i wstawiał wyjście do varchar (max). Jeśli użyto tego bezpośrednio zamiast odlewania z powrotem do odpowiedniego rozmiaru dla dostosowywanej kolumny, wydajność była bardzo słaba. Skończyło się na umieszczeniu udf na dowolnej długości z dużą nutą, zamiast polegać na wszystkich wywołujących udf, aby ponownie rzucić ciąg na mniejszy rozmiar.

Cade Roux
źródło
1

obsługa starszego systemu. Jeśli masz system, który używa danych i oczekuje się, że będzie miała określoną długość, baza danych jest dobrym miejscem do wymuszenia tej długości. To nie jest idealne, ale starsze systemy czasami nie są idealne. = P

Tony
źródło
1

Jeśli wszystkie dane w wierszu (dla wszystkich kolumn) nigdy nie zajęłyby rozsądnie 8000 lub mniej znaków, projekt w warstwie danych powinien to wymusić.

Silnik bazy danych jest znacznie wydajniejszy, utrzymując wszystko poza magazynem obiektów blob. Im mniejszy możesz ograniczyć wiersz, tym lepiej. Im więcej wierszy można wcisnąć na stronie, tym lepiej. Baza danych po prostu działa lepiej, gdy musi uzyskać dostęp do mniejszej liczby stron.

Matt Spradley
źródło
1

Moje testy wykazały, że istnieją różnice przy wyborze.

CREATE TABLE t4000 (a NVARCHAR(4000) NULL);

CREATE TABLE tmax (a NVARCHAR(MAX) NULL);

DECLARE @abc4 NVARCHAR(4000) = N'ABC';

INSERT INTO t4000
SELECT TOP 1000000 @abc4
    FROM
    master.sys.all_columns ac1,
    master.sys.all_columns ac2;

DECLARE @abc NVARCHAR(MAX) = N'ABC';

INSERT INTO tmax
SELECT TOP 1000000 @abc
    FROM
    master.sys.all_columns ac1,
    master.sys.all_columns ac2;

SET STATISTICS TIME ON;
SET STATISTICS IO ON;

SELECT * FROM dbo.t4000;
SELECT * FROM dbo.tmax;
Kvasi
źródło
0

Interesujący link: Po co używać VARCHAR, kiedy można używać TEKSTU?

Chodzi o PostgreSQL i MySQL, więc analiza wydajności jest inna, ale logika „jawności” nadal obowiązuje: po co zmusić się, aby zawsze martwić się o coś, co jest istotne przez krótki czas? Jeśli zapisałeś adres e-mail w zmiennej, użyjesz „łańcucha”, a nie „łańcucha ograniczonego do 80 znaków”.

orip
źródło
1
Jest to podobne do argumentowania, że ​​nie powinieneś mieć ograniczeń sprawdzających, aby upewnić się, że wiek danej osoby nie jest liczbą ujemną.
Jonathan Allen
Widzę różnicę między poprawnością danych a optymalizacją wydajności.
orip
0

Główną wadą, jaką widzę, jest to, że powiedzmy, że masz to:

Który zawiera najwięcej informacji o danych potrzebnych do interfejsu użytkownika?

To

            CREATE TABLE [dbo].[BusData](
                [ID] [int] IDENTITY(1,1) NOT NULL,
                [RecordId] [nvarchar](MAX) NULL,
                [CompanyName] [nvarchar](MAX) NOT NULL,
                [FirstName] [nvarchar](MAX) NOT NULL,
                [LastName] [nvarchar](MAX) NOT NULL,
                [ADDRESS] [nvarchar](MAX) NOT NULL,
                [CITY] [nvarchar](MAX) NOT NULL,
                [County] [nvarchar](MAX) NOT NULL,
                [STATE] [nvarchar](MAX) NOT NULL,
                [ZIP] [nvarchar](MAX) NOT NULL,
                [PHONE] [nvarchar](MAX) NOT NULL,
                [COUNTRY] [nvarchar](MAX) NOT NULL,
                [NPA] [nvarchar](MAX) NULL,
                [NXX] [nvarchar](MAX) NULL,
                [XXXX] [nvarchar](MAX) NULL,
                [CurrentRecord] [nvarchar](MAX) NULL,
                [TotalCount] [nvarchar](MAX) NULL,
                [Status] [int] NOT NULL,
                [ChangeDate] [datetime] NOT NULL
            ) ON [PRIMARY]

Albo to?

            CREATE TABLE [dbo].[BusData](
                [ID] [int] IDENTITY(1,1) NOT NULL,
                [RecordId] [nvarchar](50) NULL,
                [CompanyName] [nvarchar](50) NOT NULL,
                [FirstName] [nvarchar](50) NOT NULL,
                [LastName] [nvarchar](50) NOT NULL,
                [ADDRESS] [nvarchar](50) NOT NULL,
                [CITY] [nvarchar](50) NOT NULL,
                [County] [nvarchar](50) NOT NULL,
                [STATE] [nvarchar](2) NOT NULL,
                [ZIP] [nvarchar](16) NOT NULL,
                [PHONE] [nvarchar](18) NOT NULL,
                [COUNTRY] [nvarchar](50) NOT NULL,
                [NPA] [nvarchar](3) NULL,
                [NXX] [nvarchar](3) NULL,
                [XXXX] [nvarchar](4) NULL,
                [CurrentRecord] [nvarchar](50) NULL,
                [TotalCount] [nvarchar](50) NULL,
                [Status] [int] NOT NULL,
                [ChangeDate] [datetime] NOT NULL
            ) ON [PRIMARY]
Carlos Martini
źródło
3
Wolałbym, aby logika biznesowa mówiła mi, że nazwa firmy może zawierać maksymalnie 50 znaków, zamiast polegać na tabeli bazy danych dla tych informacji.
Khan,
Zgadzam się z Jeffem. Nie sądzę, aby sklep trwałości był właściwym miejscem do zdefiniowania reguł biznesowych. W architekturze warstwowej interfejs użytkownika nie wiedziałby nawet o warstwie trwałości.
stucampbell
O ile oczywiście nie używasz wartości ograniczonej do określonego rozmiaru, na przykład kodu ISO dla kraju.
Ben
2
Co to ma wspólnego z defossem tabeli? Nadal możesz mieć logikę biznesową. Myślę, że twój punkt widzenia nie ma sensu w związku ze sposobem zaprojektowania stołu. Jeśli nadal chcesz zaprojektować jakąś definicję w warstwie biznesowej, niech tak będzie. Chociaż to, co miałoby więcej sensu, to i tak użycie przechowywanego proca w warstwie biznesowej; nie def tabeli?
Carlos Martini
1
Wydaje się to niepopularne, ale zgadzam się z Carlosem, jeśli db ustawi maksymalny rozmiar, możesz być wygodny we wszystkich warstwach, które zbudujesz na nim, z czym prawdopodobnie będziesz musiał sobie poradzić. Jest to szczególnie ważne, jeśli masz wiele systemów zapisujących do bazy danych.
Tim Abell,
0

Jedną wadą jest to, że będziesz projektować wokół nieprzewidywalnej zmiennej i prawdopodobnie zignorujesz zamiast korzystać z wewnętrznej struktury danych SQL Server, stopniowo składającej się z Wiersza (ów), Strony (stron) i Zakresu (ów).

Co sprawia, że ​​myślę o wyrównaniu struktury danych w C, i że świadomość tego wyrównania jest ogólnie uważana za dobrą rzecz (TM). Podobny pomysł, inny kontekst.

Strona MSDN dla stron i zakresów

Strona MSDN dla danych przepełnienia wiersza

tsundoku
źródło
0

najpierw pomyślałem o tym, ale potem jeszcze raz. Ma to wpływ na wydajność, ale równie dobrze służy jako forma dokumentacji, aby zorientować się, jakie naprawdę są rozmiary pól. I wymusza, gdy ta baza danych znajduje się w większym ekosystemie. Moim zdaniem kluczem jest być pobłażającym, ale tylko w granicach rozsądku.

ok, oto moje odczucia w kwestii logiki biznesowej i warstwy danych. To zależy, jeśli twoja baza danych jest zasobem współdzielonym między systemami, które współużytkują logikę biznesową, to oczywiście wydaje się naturalnym miejscem do egzekwowania takiej logiki, ale to nie jest NAJLEPSZY sposób, aby to zrobić, NAJLEPSZY sposób to zapewnić interfejs API, pozwala testowana interakcja, która utrzymuje logikę biznesową tam, gdzie należy, utrzymuje systemy oddzielone od siebie, utrzymuje warstwy w systemie oddzielonym. Jeśli jednak twoja baza danych ma obsługiwać tylko jedną aplikację, pozwól AGILE pomyśleć, co jest teraz prawdą? projekt na teraz. Jeśli i kiedy taki dostęp jest potrzebny, podaj API tych danych.

oczywiście jest to jednak ideał, jeśli pracujesz z istniejącym systemem, istnieje prawdopodobieństwo, że będziesz musiał to zrobić inaczej, przynajmniej w krótkim okresie.

Stephen Whipp
źródło
-1

Spowoduje to problem z wydajnością, chociaż nigdy nie może powodować żadnych faktycznych problemów, jeśli baza danych jest mała. Każdy rekord zajmie więcej miejsca na dysku twardym, a baza danych będzie musiała odczytać więcej sektorów dysku, jeśli przeszukujesz wiele rekordów jednocześnie. Na przykład, mały rekord może zmieścić 50 w sektorze, a duży może zmieścić się w 5. Może być konieczne odczytanie 10 razy więcej danych z dysku za pomocą dużego rekordu.

Dan Goldstein
źródło
5
-1. Ciąg o długości 100 przechowywany w nvarchar(max)kolumnie nie zajmuje więcej miejsca na dysku niż w nvarchar(100)kolumnie.
Martin Smith
To, co opisujesz, jest poprawne, jeśli rozmiar przechowywanych danych jest większy, ale to pytanie dotyczy tego, czy typ danych ma wpływ na wydajność lub inne czynniki.
-2

Utrudni to projektowanie ekranu, ponieważ nie będziesz już w stanie przewidzieć, jak szerokie powinny być twoje kontrolki.

pappes
źródło