Czy powinienem dodać dowolny limit długości do kolumn VARCHAR?

35

Według dokumentacji PostgreSQL nie ma różnicy w wydajności między VARCHAR, VARCHAR(n)a TEXT.

Czy powinienem dodać dowolny limit długości do kolumny nazwy lub adresu ?

Edycja: brak duplikatu:

Wiem, że ten CHARtyp jest reliktem przeszłości i interesuję się nie tylko wydajnością, ale innymi zaletami i wadami, takimi jak Erwin w swojej niesamowitej odpowiedzi.

Daniel Serodio
źródło

Odpowiedzi:

45

Odpowiedź brzmi nie .
Nie dodawaj modyfikatora długości, varcharjeśli możesz tego uniknąć. W większości przypadków tak naprawdę nie potrzebujesz ograniczenia długości. Po prostu użyj textdla wszystkich danych postaci. Zrób to varchar(bez modyfikatora długości), jeśli chcesz zachować zgodność z RDBMS, który nie ma text.

Wydajność jest prawie taka sama - w rzadkich sytuacjachtext jest nieco szybsza , a cykle zapisujesz na sprawdzenie długości.

Jeśli faktycznie potrzebujesz wymusić maksymalną długość, nadal używaj texti dodaj ograniczenie sprawdzania :

ALTER TABLE tbl ADD CONSTRAINT tbl_col_len CHECK (length(col) < 51);

Możesz zmodyfikować lub usunąć takie ograniczenie w dowolnym momencie, bez konieczności wprowadzania zmian w definicji tabeli i wszystkich zależnych obiektach (widoki, funkcje, klucze obce, ...)

Dzięki modyfikatorom długości po prostu napotykasz problemy takie jak ta czy ta czy ta ...

PostgreSQL 9.1 wprowadził nową funkcję, która nieco łagodzi ból. Przytaczam tutaj informacje o wydaniu :

Pozwól ALTER TABLE ... SET DATA TYPEuniknąć przepisywania tabel w odpowiednich przypadkach (Noah Misch, Robert Haas)

Na przykład konwersja varcharkolumny na tekst nie wymaga już przepisania tabeli. Jednak zwiększenie ograniczenia długości varcharkolumny nadal wymaga przepisania tabeli.

Erwin Brandstetter
źródło
Myślę, że ta odpowiedź byłaby o wiele lepsza, gdyby była po prostu „nie, nigdy nie dodawaj arbitralnych ograniczeń do prawdziwej bazy danych”. Wydaje mi się, że wiele z tych odpowiedzi wymaga poprawek i dalszych informacji, ale jest to całkowicie nie na temat i odwróciłoby uwagę od twojego wniosku, z którym całkowicie się zgadzam.
Evan Carroll
Tak, wszystkie oparte na wersjach Postgres sprzed 9,1 - 6 lat temu. Trochę zakurzone, ale podstawowa rada jest nadal dobra.
Erwin Brandstetter
Czy dobrym lub złym pomysłem jest dodanie ograniczenia sprawdzania dla każdej kolumny tekstowej w celu sprawdzenia poprawności i upewnienie się, że błąd w kliencie nie zużywa całego miejsca na dysku bazy danych przez wstawienie bardzo dużego tekstu?
Kod
@Code: To realna opcja. Jeśli masz wiele kolumn z tym samym ograniczeniem, rozważ domeny . Lub w varchar(n)końcu dla uproszczenia - jeśli wady zwykle nie wpływają na ciebie. (Limit nie jest w twoim przypadku arbitralny, jeśli chcesz egzekwować faktyczną maksymalną długość.)
Erwin Brandstetter
12

Jeśli widzisz limit długości jako rodzaj ograniczenia sprawdzania, aby upewnić się, że sprawdzasz poprawność danych, to tak, dodaj go. Właściwie możesz nie używać określenia długości, lecz realne ograniczenia wyboru zamiast tego dokonać zmieniając limit szybciej.

Aby zmienić (zwiększyć) limit długości, musisz uruchomić taki, ALTER TABLEktóry może zająć dużo czasu (ze względu na możliwe ponowne zapisanie tabeli), podczas którego konieczna jest wyłączna blokada stołu.

Zmiana (tj. Upuszczenie i ponowne utworzenie) ograniczenia sprawdzania jest bardzo krótką operacją i wymaga jedynie odczytu danych tabeli, nie zmieni żadnych wierszy. Będzie to o wiele szybsze (co z kolei oznacza, że ​​wyłączna blokada stołu będzie utrzymywana przez znacznie krótszy czas).

Podczas pracy nie ma żadnej różnicy między a text, a varcharlub varchar(5000)kolumną.

koń bez imienia
źródło
z czystej ciekawości, dlaczego uważasz, że tej kontroli długości nie można wykonać w aplikacji klienckiej podczas przechwytywania danych?
PirateApp
4
@PirateApp: ponieważ bardzo często będzie więcej niż jedna aplikacja lub jakieś zewnętrzne źródło danych (pomyśl co nocny import partii). I prawie zawsze baza danych (i dane) żyją dłużej niż jedna aplikacja.
a_horse_w_no_name
2

Pytanie dotyczy w szczególności tego, czy dodanie dowolnego limitu długości do kolumn VARCHAR?

Na to odpowiedź brzmi „nie”. Nic nie usprawiedliwia dodania arbitralnego limitu, tak jak w gorszych bazach danych, które obsługują varchar(max)lub używają takich konwencji varchar(255). Jeśli jednak specyfikacja dotyczy limitu, myślę, że odpowiedź staje się znacznie bardziej złożona, szczególnie w przypadku nowoczesnych wersji PostgreSQL. I do tego skłaniałbym się ku TAK .

Moim zdaniem limit jest rozsądnym wyborem, jeśli wymaga tego specyfikacja. Zwłaszcza w przypadku bardziej rozsądnych obciążeń. Jeśli nie z innego powodu, to w celu zachowania metadanych.

Z mojej odpowiedzi tutaj, wydajność indeksu dla CHAR vs VARCHAR (Postgres) , gdzie odnoszę się do wartości metadanych.

Gdybym znalazł specyfikację z kluczami tekstowymi o zmiennej długości, które były znaczące i której ufałem, że będę mieć stałą maksymalną długość, też bym użył varchar. Nie mogę jednak wymyślić niczego, co spełniałoby te kryteria.

Evan Carroll
źródło
1

Wygląda na to, że może występować pewna różnica w wydajności, jeśli VARCHARjest regularnie używana do przechowywania bardzo dużych ciągów, ponieważ „długie ciągi są automatycznie kompresowane przez system”, a „bardzo długie wartości są również przechowywane w tabelach w tle”. Teoretycznie oznaczałoby to, że duża liczba żądań dla bardzo długiego pola łańcuchowego byłaby wolniejsza niż dla pola krótkiego łańcucha. Prawdopodobnie nigdy nie napotkasz tego problemu, ponieważ nazwy i adresy nie będą bardzo długie.

Jednak w zależności od tego, jak używasz tych ciągów poza bazą danych, możesz chcieć dodać praktyczny limit, aby zapobiec nadużyciom systemu. Na przykład, jeśli gdzieś wyświetlasz nazwę i adres w formularzu, możesz nie być w stanie wyświetlić całego akapitu tekstu w polu „nazwa”, więc sensowne byłoby ograniczenie kolumny nazwy do około 500 postacie.

Edward
źródło
1
AFAIK nie ma różnicy w TOASTingu w polach varchar i tekstowych.
dezso
VARCHARjest czysto syntaktycznym cukrem, ponieważ TEXTw Postgres nie ma różnicy w przechowywaniu; kompresja w porównaniu z pamięcią tabeli w tle jest wykonywana na podstawie faktycznej długości danych w kolumnie, a nie na metadanych kolumny. Kolumny TEXT są przechowywane wewnętrznie jako varlenastruktura C (która jest tablicą o zmiennej długości z pierwszymi 4 bajtami przechowującymi długość przy tworzeniu / aktualizacji) i ta struktura jest zoptymalizowana na podstawie jej długości.
cowbert