Jaka jest różnica między typami danych MySQL VARCHAR i TEXT?

19

Czy po wprowadzeniu wersji 5.0.3 (która pozwalała VARCHAR na 65 535 bajtów i przestała obcinać końcowe spacje), istnieje jakaś znacząca różnica między tymi dwoma typami danych?

Czytałem listę różnic i jedyne dwie z nich to:

W przypadku indeksów w kolumnach BLOB i TEXT należy określić długość prefiksu indeksu. W przypadku CHAR i VARCHAR długość prefiksu jest opcjonalna. Patrz sekcja 7.5.1, „Indeksy kolumn”.

i

Kolumny BLOB i TEKST nie mogą mieć wartości DOMYŚLNYCH.

Więc z powodu tych dwóch ograniczeń typu danych TEXT, dlaczego miałbyś używać go w varchar (65535)? Czy istnieją konsekwencje dla wydajności jednego na drugim?

Derek Downey
źródło
1
kiedy chcesz więcej niż 65535 znaków w danych?
BlackICE,
Oto całkiem niezły wątek na forum na temat testów porównawczych między varchar a tekstem: http://forums.mysql.com/read.php?24,105964,105964
podzielony
Ponieważ lista tam naprawdę dobrze spisuje wyraźne szczegóły, a ponieważ masz już wyliczoną listę różnic, nie jestem pewien, czy jest to pytanie, którego potrzebujemy na temat DBA. Czy istnieje powód, dla którego cytowana lista i powody, które podałeś, nie są w tym przypadku wystarczająco dobre? W przeciwnym razie jadę do VtC
jcolebrand
1
Zaktualizowałem swoje pytanie, ale jednym z oczywistych powodów, dla których nie jestem pewien, jest wydajność jednego nad drugim. Nie jestem pewien, czy istnieją inne nie tak oczywiste powody
Derek Downey
Czy to w porządku, że pytasz o parametry wydajności jednego z nich?
jcolebrand

Odpowiedzi:

13

podzielone połączone z pewnymi informacjami wyjaśniającymi podstawowy problem (występują różnice w wydajności), ale nie jest łatwo powiedzieć, że jedno jest zawsze lepsze od drugiego. (w przeciwnym razie nie byłoby powodu, aby mieć oba te elementy). Ponadto w MyISM maksymalny rozmiar 64k dla VARCHAR nie jest na pole - jest na rekord.

Zasadniczo istnieją 4 sposoby przechowywania ciągów w rekordach bazy danych:

  1. poprawiona długość
  2. Ciągi w stylu C (oznaczone znakiem NULL lub podobnym znakiem na końcu łańcucha)
  3. Ciągi w stylu Pascala (kilka bajtów, aby wskazać długość, a następnie ciąg)
  4. Wskaźniki (przechowuj ciąg gdzie indziej)

MyISM używa czegoś podobnego do # 3 dla VARCHAR i hybrydowego podejścia dla TEXT, w którym zapisuje początek ciągu w rekordzie, a następnie resztę łańcucha gdzie indziej. InnoDB jest podobny do VARCHAR, ale przechowuje pełne pole TEXT poza rekordem.

W przypadku 1 i 4 rzeczy w rekordzie są zawsze tej samej długości, więc łatwiej jest pominąć, jeśli nie potrzebujesz łańcucha, ale potrzebujesz rzeczy po nim. Zarówno # 2, jak i # 3 nie są takie złe dla krótkich strun ... # 2 musi szukać znacznika, podczas gdy # 3 może przeskakiwać do przodu ... w miarę wydłużania się strun, # 2 pogarsza się dla tego konkretnego zastosowania walizka.

Jeśli rzeczywiście potrzebujesz odczytać ciąg, numer 4 jest wolniejszy, ponieważ musisz odczytać rekord, a następnie przeczytaj ciąg, który może być przechowywany w innym miejscu na dysku, w zależności od tego, jak ta baza danych go obsługuje. # 1 jest zawsze dość proste i ponownie napotykasz podobne problemy, w których dla # 2 pogarsza się, im dłuższy jest ciąg, podczas gdy # 3 jest nieco gorszy niż # 2 dla bardzo małych ciągów, ale lepiej, gdy staje się dłuższy.

Potem są wymagania dotyczące przechowywania ... # 1 jest zawsze stałą długością, więc może mieć wzdęcia, jeśli większość łańcuchów nie ma maksymalnej długości. # 2 ma 1 dodatkowy bajt; # 3 zazwyczaj ma 2 dodatkowe bajty, jeśli maksymalna długość = 255, 4 dodatkowe bajty, jeśli maks. 64k. # 4 ma długość wskaźnika, a także reguły dla # 3 zazwyczaj.

W przypadku konkretnych implementacji w MySQL 5.1 stan dokumentacji MyISM :

  • Obsługa prawdziwego typu VARCHAR; kolumna VARCHAR zaczyna się od długości zapisanej w jednym lub dwóch bajtach.
  • Tabele z kolumnami VARCHAR mogą mieć stałą lub dynamiczną długość wiersza.
  • Suma długości kolumn VARCHAR i CHAR w tabeli może wynosić do 64 KB.

Choć dla InnoDB :

  • Część nagłówka rekordu o zmiennej długości zawiera wektor bitowy do wskazania NULL kolumn. Jeśli liczba kolumn w indeksie, która może wynosić NULL, wynosi N, wektor bitowy zajmuje bajty SUFITOWE (N / 8). (Na przykład, jeśli jest gdzieś od 9 do 15 kolumn, które mogą mieć wartość NULL, wektor bitowy używa dwóch bajtów.) Kolumny, które są NULL, nie zajmują miejsca innego niż bit w tym wektorze. Część nagłówka o zmiennej długości zawiera również długości kolumn o zmiennej długości. Każda długość zajmuje jeden lub dwa bajty, w zależności od maksymalnej długości kolumny. Jeśli wszystkie kolumny w indeksie NIE mają wartości NULL i mają stałą długość, nagłówek rekordu nie ma części o zmiennej długości.
  • Dla każdego pola o zmiennej długości innej niż NULL nagłówek rekordu zawiera długość kolumny w jednym lub dwóch bajtach. Dwa bajty będą potrzebne tylko wtedy, gdy część kolumny jest przechowywana zewnętrznie na stronach przepełnienia lub maksymalna długość przekracza 255 bajtów, a rzeczywista długość przekracza 127 bajtów. W przypadku kolumny przechowywanej zewnętrznie dwubajtowa długość wskazuje długość części przechowywanej wewnętrznie plus 20-bajtowy wskaźnik do części przechowywanej zewnętrznie. Część wewnętrzna ma 768 bajtów, więc długość wynosi 768 + 20. 20-bajtowy wskaźnik przechowuje prawdziwą długość kolumny.

...

podobnie jak w przypadku wielu innych rzeczy związanych z bazami danych, jeśli nie jesteś pewien, co jest najlepsze dla twoich potrzeb, spróbuj porównać je z podobnymi danymi i wykorzystaniem, i zobacz, jak się zachowują.

Joe
źródło
Nić podzielone związane stany, które przechowuje MySQL plamy i pola tekstowe inline forums.mysql.com/read.php?24,105964,267596#msg-267596
Michael Mior
1
Nitpick ... Dla wszystkich praktycznych celów nie ma limitu 64 KB w wierszu w żadnym silniku. LONGTEXTi LONGBLOBsą tego przykładem. Ciągi w stylu C nie są nigdzie używane przez MySQL (o których wiem). InnoDB stosuje podejście „hybrydowe”, ale jest bardziej złożone, w zależności od wielkości wiersza, formatu wiersza itp. Przechowywanie ciągów o „stałej” długości prawie nigdy nie jest wskazane, z wyjątkiem sytuacji, gdy faktycznie mają stałą długość (kod kraju, kod pocztowy itp.) . InnoDB ma 4 ROW_FORMATs; tekst omawia tylko 1 lub 2 z nich.
Rick James,
2

Gdy WYBÓR musi utworzyć tabelę tymczasową (na przykład w celu posortowania wyników), utworzy tabelę MEMORY lub tabelę MyISAM. PAMIĘĆ jest bardziej wydajna. Istnieją ograniczenia dotyczące PAMIĘCI - jedną z nich jest zabronienie TEKSTU i BLOBU. Dlatego SELECT może działać wolniej z TEKSTEM niż VARCHAR.

Rick James
źródło