Проблемы с производительностью jsonb в Postgres

У меня проблема с производительностью jsonb в postgres. У меня довольно много продуктов в моей базе данных, и в каждом из них есть один столбец с именем Technical_details, в котором сохраняются все технические детали, подобные этому

{ 
    detail: {
        unit: unit_name,
        value: value 
    }
} 

e.g:

{ 
    weight: { 
        unit: ‘kg’,
        value: 1000 
    } 
}

Теперь я хотел бы сделать следующий запрос:

Product Load (149.4ms) 
    SELECT "products".* FROM "products" 
    WHERE (COALESCE(CAST( nullif(technical_details#>>’{weight,value}','') AS FLOAT),0) BETWEEN 500 AND 1500)

Но, как видите, на создание такого запроса уходит много времени. Есть ли у кого-нибудь идеи, как я могу улучшить производительность такого запроса?

Большое спасибо!

Изменить: По просьбе Дмитрия: Вот те индексы, которые у меня есть, которые связаны с техническими деталями:

"index_products_on_technical_details" gin (technical_details)
"index_products_on_technical_details_width" btree ((technical_details ->> 'width'::text))
"index_products_on_technical_details_weight" btree ((technical_details ->> 'weight'::text))

Это EXPLAIN ANALYZE запрос:

Seq Scan on products  (cost=0.00..926.80 rows=22 width=1288) (actual time=0.100..30.563 rows=498 loops=1)
   Filter: ((COALESCE((NULLIF((technical_details #>> '{weight,value}'::text[]), ''::text))::double precision, 0::double precision) >= 500::double precision) AND (COALESCE((NULLIF((technical_details #>> '{weight,value}'::text[]), ''::text))::double precision, 0::double precision) <= 1500::double precision))
   Rows Removed by Filter: 3997
 Planning time: 0.236 ms
 Execution time: 30.740 ms

person VinVan    schedule 15.12.2015    source источник
comment
действительно давно не очень точное описание. Не могли бы вы предоставить конфигурацию ваших индексов (\d tableName) и EXPLAIN ANALYZE вывод?   -  person Dmitry Savinkov    schedule 15.12.2015
comment
Под словом «действительно долгое время» я имел в виду время загрузки продукта 149,4 мс, которое указано в консоли Rails. Я улучшил вопрос, указав запрошенную информацию.   -  person VinVan    schedule 16.12.2015


Ответы (1)


Вы можете создать индекс на основе выражений, чтобы ускорить его:

create index on products (
  COALESCE(CAST(nullif(technical_details#>>'{weight,value}','') AS FLOAT),0)
);

Конечно, немного странно смотреть на значения, которые могут не быть в одном и том же блоке.

person jjanes    schedule 15.12.2015