Czy powinienem używać ciągu bitów PostgreSQL?

18

bit stringOstatnio uczyłem się o typie danych i jestem bardzo ciekawy:

  1. Na dole tej strony z dokumentami znajduje się zdanie:

    ... plus 5 lub 8 bajtów narzutu w zależności od długości łańcucha

  2. W jaki sposób obsługiwane są ciągi bitów w innych językach, takich jak PHP, Java, C #, C ++ itp., Poprzez sterowniki takie jak Npgsql, ODBC itp.

W przypadku pytania nr 1 użycie smallinta lub biginta będzie znacznie bardziej wydajnym miejscem do przechowywania i być może zapewni wzrost wydajności, ponieważ liczby całkowite są obsługiwane wszędzie. Większość języków programowania z łatwością obsługuje operacje bitowe na liczbach całkowitych. Jeśli tak, to po co wprowadzać typ danych łańcuchów bitowych? Czy dotyczy to tylko przypadków wymagających dużej ilości masek bitowych? Może indeksowanie pól bitowych? Jestem ciekaw, jak indeksowanie pól bitowych odbywa się w PostgreSQL.

Jeśli chodzi o # 2, jestem zmieszany, bardziej niż ciekawy. Na przykład, co jeśli przechowuję maski bitów dnia tygodnia w polu bit (7), jeden bit na dzień, a najniższy bit reprezentuje poniedziałek. Następnie pytam o wartość w PHP i C ++. Co dostane? Dokumentacja mówi, że będę miał trochę łańcucha, jednak nie jest to coś, czego mogę użyć bezpośrednio - jak w przypadku liczb całkowitych. Czy w takim przypadku powinienem zrezygnować z bitów?

Czy ktoś może wyjaśnić, dlaczego i kiedy powinienem używać bitów lub bitów?

Jackey Cheung
źródło
2
Odpowiedź Erwina na temat SO jest świetna (i jeśli nie masz nic przeciwko kopiowaniu jej na @Erwin, dobrze byłoby mieć tutaj), ale chciałbym dodać własną ostrożność: w większości przypadków nie rozważasz przechowywania informacji w ciągach bitów w RDBMS - przy użyciu oddzielnych kolumn boolowskich w normalnym rozwiązaniu, niezależnie od „wydajności” pamięci.
Jack mówi, że spróbuj topanswers.xyz
@JackDouglas: Nie miałbym nic przeciwko kopiowaniu mojej odpowiedzi. Zastanawiam się jednak: czy powielanie odpowiedzi w witrynach SE jest dobrym pomysłem?
Erwin Brandstetter
@Erwin Nie rozumiem, dlaczego nie - strony w pewnym stopniu się pokrywają i oba powinny być samodzielne (więc na przykład nie zamknęlibyśmy - a zresztą nie moglibyśmy - zamknąć tutaj pytania jako duplikatu identyczne pytanie w sprawie SO). Koncentrujemy się bardziej na zagadnieniach „eksperckich”, ale IMO twoja odpowiedź pasuje do tej kategorii w obecnej formie :)
Jack mówi, spróbuj wypróbować topanswers.xyz
@JackDouglas: Cóż, ma sens. A zresztą jak mógłbym się nie zgodzić po pochwałach, którymi się wślizgnąłeś? ;)
Erwin Brandstetter,

Odpowiedzi:

18

Jeśli masz tylko kilka zmiennych, rozważę zachowanie oddzielnych booleankolumn.

  • Indeksowanie jest łatwe. W szczególności indeksy wyrażeń są łatwe.
  • Warunki dla zapytań i częściowego indeksowania są łatwe do napisania i odczytania oraz znaczące.
  • Kolumna logiczna zajmuje 1 bajt. W przypadku tylko kilku zmiennych zajmuje to najmniej miejsca.
  • W przeciwieństwie do innych opcji kolumny boolowskie dopuszczają NULLwartości dla poszczególnych bitów, jeśli są potrzebne. Zawsze możesz zdefiniować kolumny, NOT NULLjeśli tego nie zrobisz.

Optymalizacja pamięci

Jeśli masz więcej niż pełne zmienne pełne ręki, ale mniej niż 33, an integer kolumna może ci najlepiej służyć. (Lub a bigintdla maksymalnie 64 zmiennych.)

  • Zajmuje 4 bajty na dysku.
  • Bardzo szybkie indeksowanie dla dokładnych dopasowań ( =operator).
  • Obsługa poszczególnych wartości może być wolniejsza / mniej wygodna niż w przypadku bit string lub boolean.

Przy jeszcze większej liczbie zmiennych lub jeśli chcesz często manipulować wartościami, lub jeśli nie masz ogromnych tabel, a miejsce na dysku / pamięci RAM nie stanowi problemu, lub jeśli nie jesteś pewien, co wybrać, rozważę bit(n)lubbit varying(n) .

  • Zajmuje co najmniej 5 bajtów (lub 8 dla bardzo długich łańcuchów) plus 1 bajt dla każdej grupy 8 bitów (w zaokrągleniu w górę).
  • Możesz używać funkcji ciągów bitowych i operatorów .

Przykłady

W przypadku zaledwie 3 bitów informacji poszczególne booleankolumny zawierają 3 bajty, integerpotrzeba 4 bajtów i abit string 6 bajtów (5 + 1).

Dla 32 bitów informacji integernadal potrzebuje 4 bajtów, bit stringzajmuje 9 bajtów dla tego samego (5 + 4) iboolean kolumny zajmują 32 bajty.

Dalsza lektura

Erwin Brandstetter
źródło
Tak, zgadzam się z tobą. Obecnie używam samllint do przechowywania maski bitowej w dni powszednie. Pasował do obudowy, wydajność przechowywania / wydajność szeroka. Jednak jeśli miałbym trochę więcej indeksowania / filtrowania na maskach bitowych, to się nie powiedzie z powodu niskiej wydajności.
Jackey Cheung
3

Wszystkie typy PostgreSQL są przydatne do niektórych rzeczy, a mniej przydatne do innych. Ogólnie rzecz biorąc, bardziej martwisz się o funkcjonalność, a później o wydajność. PostgreSQL ma wiele funkcji do manipulowania różnego rodzaju typami danych i nie stanowią one wyjątku.

Oczekiwałbym, że w warstwie aplikacji, chyba że sterownik db poradzi sobie z jakąś konwersją typu, otrzymasz reprezentację ciągu i będziesz musiał to obsłużyć. Dlatego może, ale nie musi być przydatny w tej roli.

Przydatne jest, gdy chcesz wybrać rekordy na podstawie operacji bitowych, takich jak bitowa lub bitowa, lub w inny sposób manipulować danymi w zapytaniach SQL. O ile nie robisz tego, wiele bardziej ezoterycznych funkcji PostgreSQL jest mniej pomocnych.

Należy również pamiętać, że w przypadku dłuższych ciągów informacji binarnych istnieje interfejs dużych obiektów, który pozwala na przesyłanie strumieniowe itp. Oraz interfejs bytea, który umożliwia bardziej zwięzłą reprezentację ciągu.

tl; dr: Jeśli będziesz go potrzebować, będziesz o tym wiedział. W przeciwnym razie zapisz go w sekcji „zarezerwowane do przyszłego użytku”.

Chris Travers
źródło