Gdyby wszystkie wartości miały 36 znaków, wyszukiwanie indeksu byłoby zauważalnie szybsze przy użyciu char vs varchar

30

Mam starszy schemat (zastrzeżenie!), Który używa wygenerowanego na podstawie skrótu identyfikatora dla klucza podstawowego dla wszystkich tabel (jest ich wiele). Przykładem takiego identyfikatora jest:

922475bb-ad93-43ee-9487-d2671b886479

Nie ma żadnej nadziei na zmianę tego podejścia, jednak wydajność z dostępem do indeksu jest niska. Uchylenie mnóstwo powodów to może być, jest jedna rzecz zauważyłem, że wydawały mniej niż optymalna - mimo wszystkich wartości ID w każdym wielu tabel będących dokładnie 36 znaków, typ kolumna jest varchar(36), nie char(36) .

Czy zmiana typów kolumn na ustaloną długość char(36)przyniosłaby jakiekolwiek znaczące korzyści w zakresie wydajności indeksu poza bardzo niewielki wzrost liczby wpisów na stronie indeksu itp.?

Czy to znaczy, że postgres działa znacznie szybciej w przypadku typów o stałej długości niż w przypadku typów o zmiennej długości?

Proszę nie wspominać o niewielkich oszczędnościach na przechowywaniu - nie będzie to miało znaczenia w porównaniu z operacją wymaganą do zmiany kolumn.

Czech
źródło

Odpowiedzi:

40

Nie. Żadnego zysku . Podręcznik wyraźnie stwierdza :

Wskazówka: Nie ma różnicy w wydajności między tymi trzema typami , poza zwiększoną przestrzenią dyskową w przypadku korzystania z pustego pola i kilkoma dodatkowymi cyklami procesora, aby sprawdzić długość podczas przechowywania w kolumnie o ograniczonej długości. Chociaż character(n)ma przewagę wydajności w niektórych innych systemach baz danych, nie ma takiej przewagi w PostgreSQL; w rzeczywistości character(n)jest zwykle najwolniejszy z trzech ze względu na dodatkowe koszty przechowywania. W większości sytuacji text lub character varyingnależy go użyć .

Odważny nacisk moje.

char(n)jest w dużej mierze przestarzałym, bezużytecznym typem. Trzymaj się varchar(n). Jeśli nie musisz wymuszać długości, varcharlub textbyłoby to trochę szybsze. Nie będziesz w stanie zmierzyć różnicy.

Ponadto, jeśli wszystkie ciągi mają dokładnie 36 znaków, nie ma żadnej oszczędności miejsca, nawet najmniejszej. Oba mają dokładnie taki sam rozmiar na dysku i w pamięci RAM. Możesz testować za pomocą pg_column_size()(wyrażenia i kolumny tabeli).

Związane z:

Nie prosiłeś o inne opcje , ale wspomnę o dwóch:

  1. COLLATION- chyba że korzystasz z DB z sortowaniem „C” . Sortowanie jest często pomijane i być może drogie. Ponieważ wydaje się, że twoje ciągi znaków nie mają znaczenia w języku naturalnym, prawdopodobnie nie ma sensu przestrzegać COLLATIONreguł. Związane z:

    Rozbudowany test porównawczy (między innymi) wpływ COLLATE "C"na wydajność:

  2. UUID , oczywiście. Twój ciąg podejrzanie wygląda jak UUID (32 cyfry szesnastkowe plus 4 ograniczniki). O wiele bardziej wydajne byłoby przechowywanie ich jako rzeczywistegouuidtypu danych, który jest szybszy na wiele sposobów i zajmuje tylko 16 bajtów - w przeciwieństwie do 37 bajtów w pamięci RAM dla jednegochar(36)lubvarchar(36)(przechowywanych bez ograniczników, tylko 32 znaki definiujące) lub 33 bajty na dysku. Jednakw wielu przypadkach wypełnienie wyrównania spowoduje wobu przypadkach 40 bajtów.)COLLATIONByłoby również nieistotne dlauuidtypu danych.

    SELECT '922475bb-ad93-43ee-9487-d2671b886479'::uuid

    Może to być pomocne (ostatnie rozdziały):

    Zobacz też:

Erwin Brandstetter
źródło
oznacza to, że char / varchar (n) o ograniczonej długości spędzi cykle procesora na sprawdzaniu ograniczenia, podczas gdy pole tekstowe o zmiennej długości zapisuje tekst osobno w mniej przystępny sposób w porównaniu z char, który wygrywa w tym scenariuszu i jest tą wygraną warto nawet rozważyć, powiedzmy, 10 milionów wierszy z fragmentem tekstu
PirateApp
1
@PirateApp: char(n)prawie nigdy nie wygrywa pod żadnym względem. Nie używaj tego. Typy danych texti varchar(bez modyfikatora długości) są kompatybilne binarnie i mają te same parametry wydajności. Istnieją historyczne powody, dla których oba mogą współistnieć w Postgres. Wewnętrznie textjest „preferowanym” typem typu ciągu (który może wpływać na rozdzielczość typu funkcji). Cykle procesora wymuszają varchar(n)ledwie znaczenie. W razie potrzeby użyj ograniczenia długości . W omawianym przypadku uuidprawdziwy zwycięzca.
Erwin Brandstetter