Odpowiedzi:
Jest to bardzo częste „pytanie egzaminacyjne / rozmowa kwalifikacyjna”. Odpowiem tak dobrze, jak potrafię:
W standardowych formatach wierszy dla InnoDB i MyISAM (dynamiczny / kompaktowy) a VARCHAR(50)i a VARCHAR(255)będą przechowywać tekst łańcucha w ten sam sposób - 1 bajt dla długości i rzeczywisty łańcuch z 1 do 4 bajtów na znak (w zależności od kodowania i rzeczywisty zapisany znak).
W rzeczywistości, jeśli dobrze pamiętam, przypominam sobie kogoś, kto modyfikuje słownik danych za pomocą edytora szesnastkowego, aby zmienić coś w rodzaju VARCHAR(50)na a VARCHAR(100), więc można to zrobić dynamicznie (zwykle wymaga to rekonstrukcji tabeli). I było to możliwe, ponieważ zmiana nie wpłynęła na faktyczne dane.
Nie jest tak w przypadku VARCHAR(256), ponieważ zawsze wymagane są 2 bajty (przynajmniej) dla długości.
Tak, to oznacza, że zawsze powinniśmy zrobić VARCHAR(255), nie powinniśmy? Nie. Jest kilka powodów.
Podczas gdy InnoDB może przechowywać varchar w sposób dynamiczny, nie dotyczy to innych silników. MyISAM ma stały format rozmiaru wiersza, a tabele MEMORY mają zawsze stały rozmiar. Czy powinniśmy dbać o te inne silniki? Tak, powinniśmy, ponieważ nawet jeśli nie używamy ich bezpośrednio, tabele MEMORY są bardzo często używane do wyników pośrednich (tabele tymczasowe w pamięci) , a ponieważ wyniki nie są wcześniej znane, tabelę należy utworzyć z maksymalnym rozmiarem możliwe - VARCHAR(255)jeśli taki jest nasz typ. Jeśli możesz pomyśleć o zmarnowanym miejscu, jeśli używamy 'utf8' charsetkodowania MySQL , MEMORY zarezerwuje 2 bajty na długość + 3 * 255 bajtów na wiersz(dla wartości, które mogą zająć tylko kilka bajtów w InnoDB). To prawie 1 GB na 1 milion tabeli - tylko dla VARCHAR. Powoduje to nie tylko niepotrzebne obciążenie pamięci, ale może również powodować działania na dysku, co może spowalniać tysiące razy. Wszystko to z powodu złego wyboru określonego typu danych (niezależnie od zawartości).
Ma to również pewne konsekwencje dla InnoDB. Rozmiar indeksu jest ograniczony do 3072 bajtów i indeksów jednokolumnowych do 767 bajtów *. Jest więc bardzo prawdopodobne, że nie będziesz w stanie indeksować w pełniVARCHAR(255) pola (zakładając, że używasz utf8 lub innego kodowania o zmiennej długości).
Dodatkowo maksymalny rozmiar wiersza dla InnoDB wynosi pół strony (około 8000 bajtów), a pola o zmiennej długości, takie jak BLOB lub varchar, mogą być przechowywane poza stroną, jeśli nie mieszczą się na połowie strony . Ma to pewne konsekwencje w wydajności (czasem dobre, czasem złe, w zależności od użycia), których nie można zignorować. Spowodowało to pewną dziwność między formatami COMPACT i DYNAMIC. Zobacz na przykład: błąd 1118: zbyt duży rozmiar wiersza. utf8 innodb
Last but not least, jak przypomniała mi @ypercube, może być wymagany więcej niż 1 bajt dla długości, nawet jeśli używasz VARCHAR(255), ponieważ definicja jest w postaci znaków, podczas gdy długość przechowuje bajty. Na przykład REPEAT('ñ', 255)ma więcej niż 2 ^ 255 bajtów w utf8, więc do przechowywania jego długości potrzebowałby więcej niż 1 bajt:
mysql> SELECT LENGTH(REPEAT('ñ', 255));
+---------------------------+
| LENGTH(REPEAT('ñ', 255)) |
+---------------------------+
| 510 |
+---------------------------+
1 row in set (0.02 sec)
mysql> SELECT CHAR_LENGTH(REPEAT('ñ', 255));
+--------------------------------+
| CHAR_LENGTH(REPEAT('ñ', 255)) |
+--------------------------------+
| 255 |
+--------------------------------+
1 row in set (0.00 sec)
Tak więc ogólna rada polega na użyciu możliwie najmniejszego typu , ponieważ w przeciwnym razie może potencjalnie powodować problemy z wydajnością lub zarządzaniem. A VARCHAR(100)jest lepsze niż VARCHAR(255)(choć VARCHAR(20)byłoby lepsze), nawet jeśli nie znasz dokładnej długości. Staraj się być konserwatywny, ponieważ jeśli tabela nie jest zbyt duża, zawsze możesz później zmienić definicję.
Aktualizacja: Ze względu na ogromną popularność ciągów o zmiennej długości, na przykład za pomocą emoji, Oracle dąży do poprawy wydajności w tych przypadkach. W najnowszych wersjach MySQL (5.6, 5.7) InnoDB został ustawiony jako domyślny silnik zarówno wewnętrznych, jak i jawnych tabel tymczasowych, co oznacza, że pola o zmiennej długości są teraz pierwszorzędnymi obywatelami. Oznacza to, że może istnieć mniej powodów, aby mieć bardzo ograniczone długości znaków (ale nadal istnieją).
(*) Druga aktualizacja : duży_prefiks_indeks jest teraz domyślnie włączony w najnowszych wersjach MySQL (8.0), ale nadal tak jest w przypadku starszych wersji lub jeśli używasz opóźnionych formatów plików / wierszy (innych niż dynamiczne lub skompresowane), ale teraz domyślnie indeksy jednokolumnowe mogą mieć maksymalnie 3072 bajty.
Zapomnij o włączonym 1- i 2-bajtowym prefiksie VARCHARs.
Pytanie o 255 zostało zadane i udzielono odpowiedzi wiele razy.
VARCHARsmoże prowadzić do awarii CREATE TABLE.MEMORYtabele, z VARCHARsprzekształconymi w VARCHAR. Oznacza to na przykład, że VARCHAR(255) CHARACTER SET utf8mb4chce mieć stałą długość 1020 bajtów. (To się nie powiedzie i zdegeneruje się przy użyciu MyISAM.)Konkluzja: Nie używaj na ślepo 255 (lub 256); rób to, co ma sens dla schematu.