2014-10-29 12 views
13

Typy PostgreSQL bytea i bit varying brzmią podobnie:PostgreSQL: Różnica między "bytea" i "bit różnych" typów

W dokumentacji nie podano maksymalnego rozmiaru. Czy to 1GB jak character varying?

Mam dwa oddzielne przypadki użycia, zarówno nad stołem z milionami wierszy:

Przechowywanie MD5

to byłby bytea o długości 16 bajtów lub bit(128). Byłby używany do:

  • Deduplikacja: Ciężkie użycie GROUP BY, z indeksem, który przypuszczam.
  • Zapytanie z WHERE md5 = tylko w przypadku ścisłych dopasowań.
  • Wyświetlanie jako ciąg szesnastkowy do użytku przez człowieka.

Przechowywanie arbitralne dane binarne

ciągi danych binarnych o różnej długości do 4kB dla:

  • operacje bitowe znaleźć ciągi pasujące pewną maskę. Przykład na końcu tego postu.
  • Wyodrębnianie niektórych bajtów, na przykład uzyskać wartość całkowitą bajt 14 w moim ciągu.
  • Niektóre deduplikacji.

Przykład pracy dla operacji bitowej przy użyciu bit varying. Maska to X'00FF00 'i zwraca tylko wiersz X'AAAAAA'. Skróciłem ciągi dla przykładu, ale byłoby to na całej ich długości, do 4kB. Czy można zrobić coś podobnego z bytea?

CREATE TABLE test1 (mystring bit varying); 
INSERT INTO test1 VALUES (X'AAAAAA'), (X'ABCABC'); 
SELECT * FROM test1 WHERE mystring & X'00FF00' = X'00AA00'; 

Które bytea i bit varying jest bardziej odpowiedni?

Widziałem, że typ UUID jest przeznaczony do przechowywania dokładnie 16 bajtów, czy to byłaby korzyść z przechowywania MD5?

+0

nie jestem oddanie to jako odpowiedź, ponieważ jestem tu ekspertem, ale czytając ten temat , wydaje się, że bytea jest bardziej odpowiednim wyborem, szczególnie przy użyciu formatu HEX. W swoich własnych słowach PostgreSQL "Format szesnastkowy jest kompatybilny z szeroką gamą zewnętrznych aplikacji i protokołów, a jego konwersja jest szybsza niż w formacie ucieczki, dlatego preferowane jest jego użycie http://www.postgresql.org/docs /9.1/static/datatype-binary.html (konkretnie sekcja 8.4.1) i płynna odpowiedź tutaj: http://stackoverflow.com/questions/15982737/postgresql-data-type-for-md5-message-digest – JNevill

+0

I zrozumiał, że "hex" i "escape" to tylko [zewnętrzne formaty wejściowe i wyjściowe] (http://www.postgresql.org/docs/9.3/static/datatype-binary.html#DATATYPE-BINARY-TABLE). wartości wewnętrzne są binarne, więc nie zmieni nic w moim przypadku, chyba że importuję lub eksportuję ogromną liczbę wartości binarnych – Victor

+0

Cóż ... wewnętrznie to wszystko jest binarne i wydaje się, że sprowadza się do wsparcia w twoim RDBMS i jakiekolwiek narzędzia, których używasz do interakcji z nim, co popychało mnie do "bytea". Teoretycznie Char (16) i bit (128) ta ke taką samą liczbę bajtów do zapisania, więc jest to rodzaj prania z wewnętrznej perspektywy (ignorując, że istnieją oktety, których CHAR() nie może przechowywać). Jestem zaskoczony, że nie stileverflow.com super geniusze odpowiedział na to jeszcze. To dobre pytanie. – JNevill

Odpowiedz

10

Ogólnie, jeśli nie używasz operacji bitowych, powinieneś używać bytea.

przechowywać większe wartości w bytea a następnie przekonwertować podciągi do bit varying na operacje bitowe, gdzie to możliwe, ponieważ w większości klienci rozumieją bytea znacznie bardziej konsekwentnie niż bit varying i format I/O jest bardziej zwarta.

Wartości MD5 należy przechowywać jako bytea. Operacje bitowe na nich nie mają sensu, a na ogół chcesz je pobrać jako pliki binarne.

myślę bit varying naprawdę ma dwa zastosowania:

  • do przechowywania flagi pola, które są dosłownie ciągach bitów; i
  • Jako tymczasowego typu danych do obliczeń wewnętrznych

Dla prawie wszystkiego innego, użyj bytea.

Nic nie powstrzyma cię przed przechowywaniem 4-bitowego pola bitwy, jeśli tak właśnie jest.

+0

W jakim stopniu twoje zalecenie bazuje na niższym narzucie dla ciągów binarnych (1 lub 4 bajty) w porównaniu do ciągów bitowych (5 lub 8 bajtów)? –

+0

@DavidJames Przeważnie jest to logicznie czystsze i nie ma żadnego powodu, aby używać tu łańcuchów bitowych. Użyj ciągów bitowych, jeśli potrzebne są operacje bitowe, w przeciwnym razie nie. –

6
  1. Wygląda na to, że maksymalna długość bytea wynosi 1 GB. [1]
  2. Do operacji bitowej użyj bit varying (wyjaśnienie patrz poniżej)
  3. Do przechowywania skrótu MD5 bytea. To zajmie mniej pamięci niż bit varying
  4. świadczenia przy zastosowaniu UUID jest UUID algorytm jakoś gwarantuje swoją wyjątkowość, nie tylko w tabeli, ale również w bazie danych lub nawet całej bazy danych (nawet jeśli generują UUID w aplikacji). Myślę, że jeśli używasz UUID bez kresek, będzie bardziej wydajny do przechowywania, porównywania i sortowania w UUID (porównanie między bytea i UUID patrz poniżej).

Dla mnożenie użytku operacyjnego bit varying

Jeśli troska o przechowywaniu: bit varying zajmuje więcej miejsca niż bytea. Jeśli są w porządku, należy spróbować porównanie funkcji oboje oferta:

bit varying vs bytea

tej pory widzę bit varying będzie bardziej odpowiedni dla ciebie zrobić bitową operację chociaż bytea jest ogólnie przyjęty do przechowywania dowolnych danych.

PostgreSQL oferuje pojedynczy operator bytea: konkatenację. Możesz dodać jedną wartość byte do innej wartości bytea, używając operatora konkatenacji ||. [1]

Należy zauważyć, że nie można porównać dwóch wartości bytea, nawet dla równości/nierówności. Można oczywiście przekonwertować wartość bytea na inną wartość przy użyciu CAST(), co otwiera innych operatorów.[1]

Porównanie między UUID i bytea

create table u(uuid uuid primary key, payload character(300)); 
    create table b(bytea bytea primary key, payload character(300)); 

    INSERT INTO u             
    SELECT uuid_generate_v4()              
    FROM generate_series(1,1000*1000); 

    INSERT INTO b             
    SELECT random_bytea(16)              
    FROM generate_series(1,1000*1000); 

    VACUUM ANALYZE u; 
    VACUUM ANALYZE b; 

    ## Your table size 
    SELECT pg_size_pretty(pg_total_relation_size('u')); 
    pg_size_pretty 
    ---------------- 
    81 MB 

    SELECT pg_size_pretty(pg_total_relation_size('b')); 
    pg_size_pretty 
    ---------------- 
    101 MB 

    ## Speed comparison 
    \timing on 

    ## Common select 
    select * from u limit 1000; 
    Time: 1.433 ms 

    select * from b limit 1000; 
    Time: 1.396 ms 

    ## Random Select 
    SELECT * FROM u OFFSET random()*1000 LIMIT 10000; 
    Time: 42.453 ms 

    SELECT * FROM b OFFSET random()*1000 LIMIT 10000; 
    Time: 10.962 ms 

Wnioski: Nie sądzę, że będzie więcej korzyści stosując UUID wyjątkiem jego wyjątkowość i mniejszym rozmiarze (będzie szybciej wstawić)

Uwaga: brak indeksu, istnieje tylko jedno połączenie

Niektóre źródła:

  1. PostgreSQL: „Kompleksowy przewodnik do budynku, programowania i baz danych PostgreSQL Administratoring” Book
Powiązane problemy