Mam contacts
tabelę, która zawiera pola, takie jak postcode
, first name
, last name
, town
, country
, phone number
itp, z których wszystkie są zdefiniowane jako VARCHAR(255)
choć żaden z tych pól będzie kiedykolwiek zbliży się do posiadania 255 znaków. (Jeśli się zastanawiasz, dzieje się tak, ponieważ migracje Ruby on Rails VARCHAR(255)
domyślnie mapują pola typu String na i nigdy nie zadałem sobie trudu, aby go przesłonić).
Ponieważ VARCHAR przechowuje tylko liczbę rzeczywistych znaków pola (wraz z długością pola), czy jest jakaś wyraźna przewaga (wydajność lub inna) w używaniu, powiedzmy, VARCHAR(16)
nad VARCHAR(255)
?
Ponadto większość z tych pól ma indeksy. Czy większy rozmiar VARCHAR w polu w ogóle wpływa na rozmiar lub wydajność indeksu?
FYI Używam MySQL 5.
Odpowiedzi:
W magazynie
VARCHAR(255)
jest wystarczająco sprytny, aby przechowywać tylko potrzebną długość w danym wierszu, w przeciwieństwie do tego,CHAR(255)
który zawsze przechowuje 255 znaków.Ale ponieważ oznaczyłeś to pytanie za pomocą MySQL, wspomnę o wskazówce specyficznej dla MySQL: gdy wiersze są kopiowane z warstwy silnika pamięci do warstwy SQL,
VARCHAR
pola są konwertowane,CHAR
aby uzyskać przewagę pracy z wierszami o stałej szerokości. Zatem ciągi w pamięci są dopełniane do maksymalnej długości zadeklarowanejVARCHAR
kolumny.Gdy zapytanie niejawnie generuje tabelę tymczasową, na przykład podczas sortowania lub
GROUP BY
, może to zająć dużo pamięci. Jeśli używasz wieluVARCHAR(255)
pól na dane, które nie muszą być tak długie, może to spowodować, że tabela tymczasowa będzie bardzo duża.Możesz również chcieć wiedzieć, że to zachowanie "wypełnienia" oznacza, że ciąg zadeklarowany za pomocą zestawu znaków utf8 wypełnia do trzech bajtów na znak, nawet dla łańcuchów, które przechowujesz z zawartością jednobajtową (np. Znaki ascii lub latin1). Podobnie zestaw znaków utf8mb4 powoduje, że ciąg w pamięci jest wypełniony do czterech bajtów na znak.
Tak więc
VARCHAR(255)
w utf8 przechowywanie krótkiego ciągu, takiego jak „Brak opinii”, zajmuje 11 bajtów na dysku (dziesięć znaków z małymi znakami plus jeden bajt na długość), ale zajmuje 765 bajtów w pamięci, a więc w tabelach tymczasowych lub posortowanych wynikach.Pomogłem użytkownikom MySQL, którzy często nieświadomie tworzyli tabele tymczasowe o pojemności 1,5 GB i zapełniali przestrzeń dyskową. Mieli wiele
VARCHAR(255)
kolumn, które w praktyce przechowywały bardzo krótkie ciągi.Najlepiej zdefiniować kolumnę na podstawie typu danych, które zamierzasz przechowywać. Ma zalety wymuszania ograniczeń związanych z aplikacjami, jak wspominali inni ludzie. Ale ma fizyczne zalety, aby uniknąć marnowania pamięci, które opisałem powyżej.
Trudno oczywiście wiedzieć, jaki jest najdłuższy adres pocztowy, dlatego wiele osób wybiera długi
VARCHAR
, z pewnością dłuższy niż jakikolwiek adres. A 255 jest zwyczajowe, ponieważ jest to maksymalna długość a,VARCHAR
dla której długość można zakodować jednym bajtem. Była to również maksymalnaVARCHAR
długość w MySQL starsza niż 5.0.źródło
255
został użyty tak, aby długość ciągu mogła zmieścić się w jednym bajcieOprócz kwestii związanych z rozmiarem i wydajnością związanych z ustawieniem rozmiaru varchar (i być może ważniejszym, ponieważ przechowywanie i przetwarzanie tańszą co sekundę), wadą używania varchar (255) „tylko dlatego” jest zmniejszona integralność danych .
Zdefiniowanie maksymalnych limitów dla łańcuchów jest dobrą rzeczą do zrobienia, aby zapobiec wprowadzaniu dłuższych niż oczekiwane ciągów do RDBMS i powodowaniu przepełnień buforu lub wyjątków / błędów później podczas pobierania i analizowania wartości z bazy danych, które są dłuższe (więcej bajtów) niż oczekiwano.
Na przykład, jeśli masz pole, które akceptuje dwuznakowe ciągi znaków dla skrótów krajów, nie masz żadnego powodu, aby oczekiwać, że Twoi użytkownicy (w tym kontekście programiści) będą wprowadzać pełne nazwy krajów. Ponieważ nie chcesz, aby wpisywali „Antigua i Barbuda” (AG) lub „Wyspy Heard i McDonalda” (HM), nie zezwalasz na to w warstwie bazy danych. Jest również prawdopodobne, że niektórzy programiści nie przygotowali jeszcze RTFM dokumentacji projektowej ( która z pewnością istnieje ), aby wiedzieć, aby tego nie robić.
Ustaw pole tak, aby akceptowało dwa znaki i pozwól systemowi RDBMS sobie z nim poradzić (z wdziękiem przez obcięcie lub niezręcznie przez odrzucenie ich kodu SQL z błędem).
Przykłady prawdziwych danych, które nie mają powodu, aby przekraczać określoną długość:
I tak dalej...
Poświęć trochę czasu na przemyślenie swoich danych i ich ograniczeń. Jeśli jesteś architektem, programistą lub programistą, w końcu to twoja praca .
Używając varchar (n) zamiast varchar (255), eliminujesz problem polegający na tym, że użytkownicy (użytkownicy końcowi, programiści, inne programy) wprowadzają nieoczekiwanie długie dane , które wrócą później, by prześladować twój kod.
I nie powiedziałem, że nie należy również implementować tego ograniczenia w kodzie logiki biznesowej używanej przez aplikację.
źródło
the design documentation (which surely exists)
Hah. : DJestem z tobą. Precyzyjna dbałość o szczegóły jest uciążliwa i ma ograniczoną wartość.
Kiedyś dysk był cennym towarem i zwykliśmy pocić się, aby go zoptymalizować. Cena przechowywania spadła 1000-krotnie, przez co czas spędzony na wyciskaniu każdego bajtu jest mniej cenny.
Jeśli używasz tylko pól CHAR, możesz uzyskać wiersze o stałej długości. Może to zaoszczędzić trochę rzeczywistego przekształcenia dysku, jeśli wybrałeś dokładne rozmiary pól. Możesz uzyskać bardziej gęsto upakowane dane (mniej we / wy dla skanów tabel) i szybsze aktualizacje (łatwiejsze do zlokalizowania otwartych przestrzeni w bloku dla aktualizacji i wstawień).
Jeśli jednak przeszacujesz swoje rozmiary lub rzeczywiste rozmiary danych są zmienne, stracisz miejsce na pola CHAR. Dane będą mniej gęsto upakowane (co prowadzi do większej liczby wejść / wyjść dla dużych pobrań).
Ogólnie rzecz biorąc, korzyści w zakresie wydajności wynikające z próby umieszczenia rozmiaru na zmiennych zmiennych są niewielkie. Możesz łatwo wykonać test porównawczy, używając VARCHAR (255) w porównaniu z CHAR (x), aby sprawdzić, czy możesz zmierzyć różnicę.
Czasami jednak muszę podać „małą”, „średnią”, „dużą” wskazówkę. Więc używam 16, 64 i 255 dla rozmiarów.
źródło
W dzisiejszych czasach nie mogę sobie wyobrazić, że to naprawdę ma znaczenie.
Korzystanie z pól o zmiennej długości wiąże się z obciążeniem obliczeniowym, ale przy dzisiejszym nadmiarze procesorów nie jest to warte rozważenia. Systemy I / O są tak powolne, że nie istnieją żadne koszty obliczeniowe związane z efektywną obsługą varcharów. W rzeczywistości, obliczeniowo cena varchar jest prawdopodobnie wygraną netto w stosunku do ilości zaoszczędzonej przestrzeni dyskowej dzięki zastosowaniu pól o zmiennej długości na polach o stałej długości. Najprawdopodobniej masz większą gęstość rzędów.
Złożoność pól varchar polega na tym, że nie można łatwo zlokalizować rekordu na podstawie jego numeru. Kiedy masz rozmiar wiersza o stałej długości (z polami o stałej długości), obliczenie bloku dysku, na który wskazuje identyfikator wiersza, jest trywialne. Przy zmiennej długości wiersza, ten rodzaj wychodzi przez okno.
Więc teraz musisz zachować jakiś indeks numeru rekordu, tak jak każdy inny klucz podstawowy, LUB musisz utworzyć solidny identyfikator wiersza, który koduje szczegóły (takie jak blok itp.) Do identyfikatora. Jeśli to zrobisz, identyfikator będzie musiał zostać ponownie obliczony, jeśli kiedykolwiek wiersz zostanie przeniesiony do pamięci trwałej. Nic wielkiego, wystarczy przepisać wszystkie wpisy indeksu i upewnić się, że a) nigdy nie ujawniasz tego konsumentowi lub b) nigdy nie twierdzisz, że liczba jest wiarygodna.
Ale ponieważ mamy dzisiaj pola varchar, jedyną wartością varchar (16) w porównaniu z varchar (255) jest to, że DB wymusi ograniczenie 16 znaków na varchar (16). Jeśli model bazy danych ma być rzeczywiście reprezentatywny dla fizycznego modelu danych, wtedy posiadanie długości pól może mieć wartość. Jeśli jednak jest to po prostu „przechowywanie”, a nie „model ORAZ przechowywanie”, nie ma takiej potrzeby.
Następnie wystarczy rozróżnić między polem tekstowym, które jest indeksowalne (takie varchar), a czymś, co nie jest (jak pole tekstowe lub pole CLOB). Indeksowalne pola mają zwykle ograniczenie rozmiaru, aby ułatwić indeksowanie, podczas gdy pola CLOB nie (w granicach rozsądku).
źródło
Z mojego doświadczenia wynika, że jeśli pozwolisz na typ danych o długości 255 znaków, jakiś głupi użytkownik (lub jakiś doświadczony tester) faktycznie to wypełni.
Następnie masz różnego rodzaju problemy, w tym ilość miejsca przeznaczonego na te pola w raportach i wyświetlanych na ekranie aplikacji. Nie wspominając o możliwości przekroczenia limitu na wiersz danych w Twojej bazie danych (jeśli masz więcej niż kilka z tych 255 znaków).
Znacznie łatwiej jest wybrać rozsądny limit na początku, a następnie wymusić go za pośrednictwem aplikacji i bazy danych.
źródło
Dobrą praktyką jest przydzielanie tylko trochę ponad to, czego potrzebujesz. Numery telefonów nigdy nie byłyby tak duże.
Jednym z powodów jest to, że jeśli nie przeprowadzisz walidacji pod kątem dużych wpisów, bez wątpienia ktoś użyje wszystkiego, co jest. Wtedy może zabraknąć miejsca w rzędzie. Nie jestem pewien co do limitu MySQL, ale 8060 to maksymalny rozmiar wiersza w MS SQL.
Bardziej normalna wartość domyślna to 50 imho, a następnie zwiększanie w razie potrzeby.
źródło
W kontekście mysql może to stać się ważne podczas pracy z indeksami we wspomnianych kolumnach varchar, ponieważ mysql ma max. limit 767 bajtów na wiersz indeksu.
Oznacza to, że dodając indeks w kilku kolumnach varchar 255 można dość szybko / jeszcze szybciej osiągnąć ten limit na kolumnach utf8 lub utf8mb4, jak wskazano w odpowiedziach powyżej
źródło