tl; drPobieranie wielu wartości z dużego pola jsonb szybciej (PostgreSQL 9.4)
Korzystanie PSQL 9.4, czy jest jakiś sposób, aby pobrać wiele wartości z pola jsonb, takie jak w przypadku funkcji urojonej :
jsonb_extract_path(x, ARRAY['a_dictionary_key', 'a_second_dictionary_key', 'a_third_dictionary_key'])
z nadzieją na przyspieszenie czasu inaczej prawie liniowy wymagane, aby wybrać wiele wartości (wartość = 1, 2 wartości 300ms = 450ms, 3 wartości = 600ms)
Tło
I mają następujące jsonb tabeli:
CREATE TABLE "public"."analysis" (
"date" date NOT NULL,
"name" character varying (10) NOT NULL,
"country" character (3) NOT NULL,
"x" jsonb,
PRIMARY KEY(date,name)
);
z około 100 000 wierszy, z których każdy posiada rzędy słownika jsonb z ponad 90 przycisków i odpowiadających im wartości.Próbuję napisać zapytanie SQL, aby zaznaczyć kilka (< 10) + klawisz wartości w dość szybki sposób (< 500 ms)
indeks i odpytywania: 190ms
I rozpoczęte przez dodanie index:
CREATE INDEX ON analysis USING GIN (x);
to sprawia odpytywanie na podstawie wartości w "x" słowniku szybko, jak to:
SELECT date, name, country FROM analysis where date > '2014-01-01' and date < '2014-05-01' and cast(x#>> '{a_dictionary_key}' as float) > 100;
ten trwa ~ 190 ms (dopuszczalne dla nas)
Odzyskiwanie słownika wartości
Jednakże raz rozpocząć dodawanie kluczy do powrotu w SELECT części, czas realizacji wzrasta prawie liniowy:
1 Wartość: 300 ms
select jsonb_extract_path(x, 'a_dictionary_key') from analysis where date > '2014-01-01' and date < '2014-05-01' and cast(x#>> '{a_dictionary_key}' as float) > 100;
przyjmuje 366ms (+ 175ms)
select x#>'{a_dictionary_key}' as gear_down_altitude from analysis where date > '2014-01-01' and date < '2014-05-01' and cast(x#>> '{a_dictionary_key}' as float) > 100 ;
przyjmuje 300MS (+ 110ms)
3 wartości: 600ms
select jsonb_extract_path(x, 'a_dictionary_key'), jsonb_extract_path(x, 'a_second_dictionary_key'), jsonb_extract_path(x, 'a_third_dictionary_key') from analysis where date > '2014-01-01' and date < '2014-05-01' and cast(x#>> '{a_dictionary_key}' as float) > 100;
przyjmuje do 600ms (+410, +100 i dla każdej z wybranych wartości)
select x#>'{a_dictionary_key}' as a_dictionary_key, x#>'{a_second_dictionary_key}' as a_second_dictionary_key, x#>'{a_third_dictionary_key}' as a_third_dictionary_key from analysis where date > '2014-01-01' and date < '2014-05-01' and cast(x#>> '{a_dictionary_key}' as float) > 100 ;
przyjmuje do 600ms (+410 lub +100 dla każdej wybranej wartości)
Odzyskiwanie więcej wartości szybciej
Czy istnieje sposób, aby pobrać wiele wartości z pola jsonb, takie jak w przypadku funkcji urojonej:
jsonb_extract_path(x, ARRAY['a_dictionary_key', 'a_second_dictionary_key', 'a_third_dictionary_key'])
które mogłyby przyspieszyć te wyszukiwań. Może zwracać je jako kolumny lub jako listę/tablicę lub nawet obiekt json.
Odzyskiwanie tablicę używając PL/Python
Tylko do cholery to zrobiłem funkcji niestandardowej przy użyciu PL/Python, ale to było znacznie wolniejsze (5s +), prawdopodobnie z powodu json.loads:
CREATE OR REPLACE FUNCTION retrieve_objects(data jsonb, k VARCHAR[])
RETURNS TEXT[] AS $$
if not data:
return []
import simplejson as json
j = json.loads(data)
l = []
for i in k:
l.append(j[i])
return l
$$ LANGUAGE plpython2u;
# Usage:
# select retrieve_objects(x, ARRAY['a_dictionary_key', 'a_second_dictionary_key', 'a_third_dictionary_key']) from analysis where date > '2014-01-01' and date < '2014-05-01'
Aktualizacja 2015-05-21
i ponownie wprowadzone do stołu za pomocą hstore z indeksem gin i wydajności jest niemal identyczna do korzystania jsonb, nie znaczy pomocne w moim przypadku.
Dla 3 kolumn, użycie '->' trwa 560ms, vs 580ms z '#>'. Próbowałem z tabelą tymczasową, używając 'wybierz x do ....', a następnie wybierając z tej listy, która zajmuje 650ms –
Czy czas dla tabeli tymczasowej zmienia się po dodaniu/usunięciu kolumn? Wydaje się, że 100ms jest dziwaczne w wyszukiwaniu słownika, można się tego spodziewać w ciągu nanosekund. – Andomar
Utworzenie tabeli tymczasowej zajmuje 200ms, a następnie 150ms dla 1 wartości, 285ms dla 2 wartości i 460ms dla 3 wartości. Zastanawiam się, czy postgresql dekoduje json dla każdego wyszukiwania, ale tak nie powinno być (szczególnie nie dla jsonb) –