Znaczenie długości varchar w tabeli MySQL

112

Mam tabelę MySQL, w której wiersze są wstawiane dynamicznie. Ponieważ nie mam pewności co do długości sznurków i nie chcę, aby były odcinane, robię je na varchar (200), który jest generalnie znacznie większy niż potrzebuję. Czy danie polu varchar o wiele dłuższego niż to konieczne, ma duży wpływ na wydajność?

Brian
źródło
Tabela z pojedynczą indeksowaną VARCHAR(255) utf8mb4kolumną z ~ 150 tys. Wierszy o wielkości 11,5 MB. Tabela z VARCHAR(48) utf8mb4indeksowaną kolumną z tymi samymi danymi (maksymalna długość 46 znaków) wykorzystywała 4,5 MB. Nie jest to duża różnica w zapytaniach, jest indeksowana. Ale sumuje się z zapytaniami we / wy i takimi rzeczami, jak kopie zapasowe baz danych.
Code4R7

Odpowiedzi:

59

Nie, w tym sensie, że jeśli wartości, które przechowujesz w tej kolumnie, mają zawsze (powiedzmy) mniej niż 50 znaków, oznacza to, że kolumna jest taka sama varchar(50)lub varchar(200)ma taką samą wydajność.

Alex Martelli
źródło
9
Nie do końca prawda. Zobacz odpowiedź Billa Karwina
hejdav
5
Myślę, że odpowiedź typu powinna być poparta dokumentacją, testami porównawczymi lub czymś podobnym.
Gokhan Sari
301

Jest jeden możliwy wpływ na wydajność: w MySQL tymczasowe tabele i MEMORYtabele przechowują VARCHARkolumnę jako kolumnę o stałej długości, wypełnioną do maksymalnej długości. Jeśli projektujesz VARCHARkolumny o wiele większe niż największy rozmiar, jakiego potrzebujesz, zużyjesz więcej pamięci niż musisz. Wpływa to na wydajność pamięci podręcznej, szybkość sortowania itp.

Bill Karwin
źródło
33
+1. Wydaje mi się również, że niektóre sterowniki JDBC przydzielają wystarczającą ilość miejsca dla maksymalnego rozmiaru podczas konfigurowania buforów do pobierania wierszy. Nie trzeba dodawać, że powoduje to wiele niepokoju i zgrzytania zębami, gdy jakiś klaun właśnie zrobił varchar (50000) na wypadek, gdyby ktoś miał naprawdę duże nazwisko :-)
paxdiablo
21
+1. To ważny wpływ i uważam, że jest to prawdziwa odpowiedź na to pytanie.
Emre Yazici
6
Zarówno ta odpowiedź, jak i zaakceptowana odpowiedź są niezbędne do zrozumienia prawidłowej odpowiedzi na PO.
kd8azz
2
W rzeczywistości, gdy taka MEMORYtabela zostanie uznana za zbyt dużą, jest zapisywana na dysk, powodując znaczne obniżenie wydajności.
Timo
1
Ta odpowiedź mogłaby zrobić z określeniem, które silniki pamięci masowej są prawdziwe (zauważam, że dev.mysql.com/doc/refman/8.0/en/… wskazuje, że tabele tymczasowe są zawsze InnoDB od MySQL 8; czy to coś zmienia?) oraz linki do dokumentów, które zawierają kopie zapasowe roszczeń. Z tego, co widziałem na temat twoich wyników na Stack Exchange, wierzę, że miałeś rację, pisząc to, ale rzeczy mogły się zmienić, a linki byłyby dobrym przykładem dla innych i pomogłyby nauczyć resztę tego rodzaju informacje dla siebie.
Mark Amery
14

VARCHAR jest idealny do opisywanej sytuacji, ponieważ oznacza „znak zmiennej” - limit, w oparciu o Twój przykład, wynosiłby 200 znaków, ale cokolwiek mniejszego jest akceptowane i nie wypełni wyznaczonego rozmiaru kolumny.

VARCHAR również zajmuje mniej miejsca - wartości są przechowywane jako jednobajtowy lub dwubajtowy prefiks długości plus dane. Prefiks długości wskazuje liczbę bajtów wartości. Kolumna używa jednego bajtu długości, jeśli wartości wymagają nie więcej niż 255 bajtów, dwóch bajtów długości, jeśli wartości mogą wymagać więcej niż 255 bajtów.

Aby uzyskać więcej informacji na temat porównania typów danych MySQL CHAR z typami danych VARCHAR, skorzystaj z tego łącza .

Kucyki OMG
źródło
1
wszyscy zainteresowani przechowywaniem MySQL (o CHAR i VARCHAR) powinni przeczytać odnośnik wymieniony w tej odpowiedzi. Dzięki!
Pascal
14

Rozmiar to wydajność! Im mniejszy rozmiar, tym lepiej. Nie dzisiaj ani nie jutro, ale któregoś dnia Twoje stoły urosną do rozmiarów, jeśli chodzi o poważne wąskie gardła, bez względu na to, jaki projekt wybierzesz. Ale możesz przewidzieć niektóre z tych potencjalnych wąskich gardeł w fazie projektowania, które prawdopodobnie wystąpią jako pierwsze, i spróbować wydłużyć czas, w którym Twoja baza danych będzie działać szybko i szczęśliwie, dopóki nie będziesz musiał przemyśleć swojego schematu lub skalować w poziomie, dodając więcej serwerów.

W twoim przypadku istnieje wiele przecieków wydajności, na które możesz napotkać: duże łączenia są prawie niemożliwe w przypadku długich varcharkolumn. Indeksowanie na tych kolumnach jest prawdziwym zabójcą. Twój dysk musi przechowywać dane. Jedna strona pamięci może pomieścić mniej wierszy, a skanowanie tabeli będzie znacznie wolniejsze. Również pamięć podręczna zapytań prawdopodobnie nie pomoże Ci tutaj.

Musisz zadać sobie pytanie: ile wkładek może się zdarzyć rocznie? Jaka jest średnia długość? Czy naprawdę potrzebuję więcej niż 200 znaków, czy mogę to złapać w interfejsie mojej aplikacji, nawet informując użytkowników o maksymalnej długości? Czy mogę podzielić tabelę na wąską w celu szybkiego indeksowania i skanowania oraz drugą na przechowywanie dodatkowych, rzadziej potrzebnych danych o powiększającym się rozmiarze? Czy mogę wpisać możliwe dane varchar w kategorie i wyodrębnić niektóre dane w kilku mniejszych, być może kolumnach typu int lub bool, i zawęzić kolumnę varchar w ten sposób?

Tutaj możesz wiele zrobić. Najlepiej byłoby przyjąć pierwsze założenie, a następnie projektować ponownie krok po kroku, korzystając z rzeczywistych, zmierzonych danych dotyczących wydajności. Powodzenia.

Szturchać
źródło
+1 za opcje projektowania aukcji i odkrywanie wpływu. Bardzo pomocne również w przypadku mojego pytania. stackoverflow.com/q/12083089/181638
Assad Ebrahim,
5
Czy ustawienie dużej maksymalnej długości ma jakikolwiek rzeczywisty wpływ na wydajność, czy też wydajność zależy tylko od rzeczywistego rozmiaru?
poolie
5

Występ? Nie. Magazyn dyskowy? Tak, ale jest tanie i obfite. Prawdopodobnie wszystko w porządku, chyba że Twoja baza danych rozwinie się do skali terabajtów.

duffymo
źródło
Dziwne, że ta odpowiedź została odrzucona sześć lat po jej opublikowaniu, a żadna z pozostałych nie została. Wydaje się mściwy i małostkowy. W tej odpowiedzi nie ma nic niepoprawnego. Moderatorzy?
duffymo
1
Jak powiedziano, ma to wpływ na wydajność. Również miejsce na dysku nie jest darmowe. Szersza kolumna oznacza więcej odczytów / zapisów na dysku (a dostęp do dysku jest powolny), a także szersze indeksy, co zmniejsza ich użyteczność. Obie rzeczy mają negatywny wpływ na wydajność. Może to nieistotne w przypadku małej bazy danych, ale w skali gigabajtów / terabajtów na pewno będzie to miało znaczenie, jak powiedziałeś. Dla tabeli rejestrów 100 nie ma to znaczenia.
Alejandro
5

Niektórzy z was mylą się myśląc, że a varchar(200)zajmuje więcej miejsca na dysku niż plik varchar(20). Nie o to chodzi. Dopiero gdy przekroczysz 255 znaków, mysql użyje dodatkowego bajtu do określenia długości varchardanych pola.

DCH
źródło
9
Nie dotyczy to tymczasowych tabel i MEMORYtabel.
Wyścigi lekkości na orbicie,
4
Za każdym razem, gdy zapytanie wybierające używa tymczasowej tabeli (między innymi grupowania i sortowania według operacji), konwertuje varchar (200) na char (200), co obniża wydajność.
Jamie,
1

Mogą wystąpić hity wydajności - ale zwykle nie na poziomie, który większość użytkowników zauważyłaby.

Gdy rozmiar każdego pola jest znany z góry, MySQL wie dokładnie, ile bajtów znajduje się między każdym polem / wierszem i może przesuwać się dalej bez czytania wszystkich danych. Użycie zmiennych znaków osłabia tę możliwość optymalizacji.

Czy varchar powoduje spadek wydajności z powodu fragmentacji danych?

Jeszcze lepiej, char vs varchar .

W przypadku większości zastosowań wystarczy jedno z nich - ale jest różnica, aw przypadku baz danych na dużą skalę istnieją powody, dla których wybierzesz jedną lub drugą.

Rizwan Kassim
źródło
0

Będąc varchar, a nie tylko char, rozmiar jest oparty na polu wewnętrznym, które wskazuje jego rzeczywistą długość i sam ciąg. Tak więc użycie varchar (200) nie różni się zbytnio od używania varchar (150), z wyjątkiem tego, że masz potencjał, aby przechowywać więcej.

Zastanów się, co dzieje się po aktualizacji, gdy rośnie wiersz. Ale jeśli jest to rzadkie, powinno być dobrze.

Rob Farley
źródło
0

zgodnie z nazwą typu danych sugeruje, że jest to VARCHAR, tj. przechowywanie danych ze zmiennymi znakami, sam silnik mysql alokuje używaną pamięć zgodnie z przechowywanymi danymi, więc zgodnie z moją wiedzą nie ma wydajności.

user2903114
źródło
0

Powinieneś spróbować wyświetlić kolumnę varchar tak samo, jak kolumnę char w większości scenariuszy i ostrożnie ustawić długość. Nie musisz zawsze myśleć o modyfikatorze var, ale o czymś, co wpływa na podejmowanie decyzji o maksymalnej długości. To naprawdę powinno być postrzegane jako wskazówka dotycząca wydajności zamiast tego, że dostarczone struny będą miały różną długość.

Nie jest to dyrektywa, której muszą ściśle przestrzegać wewnętrzne elementy bazy danych, można ją całkowicie zignorować. Uważaj jednak, ponieważ czasami implementacja może przeciekać (na przykład stała długość i wyściółka), nawet jeśli nie powinno to być w idealnym świecie.

Jeśli masz varchar (255), nie masz gwarancji, że pod względem wydajności zawsze będzie zachowywał się inaczej niż char (255) w każdych okolicznościach.

Może wydawać się łatwe ustawienie wartości, takiej jak 255, 65535 itd., Zgodnie z poradami zawartymi w podręczniku dotyczącymi wymagań dotyczących przechowywania. Daje to wrażenie, że każda wartość od 0 (tak, to jest rzecz) do 255 będzie miała taki sam wpływ. Jednak nie można tego w pełni zagwarantować.

Wymagania dotyczące przechowywania są zwykle prawdziwe lub dobrym wskaźnikiem dla przyzwoitych i dojrzałych silników pamięci trwałej pod względem przechowywania wierszy. Nie jest to tak silny wskaźnik dla rzeczy takich jak indeksy.

Czasami jest to trudne pytanie, jak długo powinien być kawałek sznurka, więc ustawiając go na najwyższą granicę, wiesz, że powinien znajdować się w środku, ale to nie ma wpływu. Niestety, często jest to coś, co użytkownik musi rozwiązać i jest to naprawdę nieco arbitralne. Naprawdę nie można powiedzieć, że nigdy nie przesadzono z sznurkiem, ponieważ mogą być przypadki, w których nie jesteś do końca pewien.

Powinieneś upewnić się, że zapytania MySQL generują błąd, gdy łańcuch jest zbyt długi, a nie jest obcięty, abyś przynajmniej wiedział, czy może być za krótki z powodu emisji błędów. Zmiana rozmiaru kolumn w celu ich powiększenia lub zmniejszenia może być kosztowną operacją DDL, należy o tym pamiętać.

Zestaw znaków należy również wziąć pod uwagę, gdy w grę wchodzi długość i wydajność. Długość odnosi się do tego, a nie do bajtów. Jeśli na przykład używasz utf8 (nie MB4), to varchar (255) jest naprawdę varbinary (3 * 255). Trudno jest wiedzieć, jak naprawdę potoczą się takie rzeczy bez uruchamiania testów i wnikania w kod źródłowy / dokumentację. Z tego powodu nadmierna długość może mieć nieoczekiwanie zawyżony wpływ. dotyczy to nie tylko wydajności. Jeśli pewnego dnia będziesz musiał zmienić zestaw znaków kolumny varchar na większy, możesz skończyć z osiągnięciem jakiegoś limitu bez możliwości regresu, jeśli pozwolisz na występowanie nieuzasadnionych długich ciągów, których można było uniknąć. Zwykle jest to dość niszowy problem, ale pojawia się,

Jeśli okaże się, że MAX (LENGTH (kolumna)) jest zawsze <64 (na przykład, jeśli zdecydowano, że będzie ograniczenie wejściowe, które nie jest zgodne z definicją kolumny), ale masz varchar (255), to istnieje duża szansa, że ​​w niektórych scenariuszach zużyjesz cztery razy więcej miejsca niż potrzeba.

Może to obejmować:

  • Różne silniki, niektórzy mogą to całkowicie ignorować.
  • Rozmiary buforów, na przykład aktualizacja lub wstawianie, mogą wymagać przydzielenia pełnych 255 (chociaż nie sprawdziłem kodu źródłowego, aby to udowodnić, jest to tylko hipotetyczne).
  • Indeksy, będzie to od razu oczywiste, jeśli spróbujesz utworzyć klucz złożony z wielu kolumn varchar (255).
  • Tabele pośrednie i ewentualnie zestawy wyników. Biorąc pod uwagę sposób działania transakcji, nie zawsze może być możliwe użycie rzeczywistej maksymalnej długości ciągów w kolumnie w przeciwieństwie do zdefiniowanego limitu.
  • Wewnętrzne optymalizacje predykcyjne mogą przyjmować maksymalną długość jako dane wejściowe.
  • Zmiany w wersjach implementacji baz danych.

Z reguły nie ma potrzeby, aby varchar był dłuższy niż powinien, problemy z wydajnością lub nie, więc radzę trzymać się tego, kiedy możesz. Podjęcie większego wysiłku w celu sprawdzenia rozmiaru danych, narzucenia prawdziwego limitu lub znalezienia prawdziwego limitu poprzez zapytanie / badanie jest idealnym podejściem.

Jeśli nie możesz, jeśli chcesz zrobić coś takiego jak varchar (255) w przypadkach, gdy masz wątpliwości, polecam zrobienie nauki. Może to polegać na powieleniu tabeli, zmniejszeniu rozmiaru kolumny var char, a następnie skopiowaniu do niej danych z oryginału i sprawdzeniu rozmiaru danych indeksu / wierszy (indeksuj również kolumnę, spróbuj również jako klucza podstawowego, który może zachowywać się inaczej w InnoDB, ponieważ wiersze są uporządkowane według klucza podstawowego). W ten sposób przynajmniej dowiesz się, czy masz wpływ na IO, co jest jednym z najbardziej wrażliwych wąskich gardeł. Testowanie zużycia pamięci jest trudniejsze, ciężko jest to wyczerpująco przetestować. Poleciłbym przetestowanie potencjalnych najgorszych przypadków (zapytania z wieloma pośrednimi wynikami w pamięci, sprawdź z wyjaśnieniem dla dużych tabel tymczasowych itp.).

Jeśli wiesz, że w tabeli nie będzie wielu wierszy, nie będziesz używać kolumny do łączenia, indeksów (szczególnie złożonych, unikalnych) itp., To najprawdopodobniej nie będziesz mieć wielu problemów.

jgmjgm
źródło