#postgresql #sql-order-by
Вопрос:
Я пытаюсь получить упорядоченные и отфильтрованные данные из таблицы с 10 миллионами строк. Проблема ordered by
в том, что в этом случае работа идет очень медленно. Количество комбинаций фильтрации очень велико, я не могу предсказать, что все они создадут кэш в правильном порядке. Кроме того, мои данные могут часто изменяться. Другими словами, мне действительно нужно сортировать свои данные с каждым запросом.
Я попытался погуглить его и понял, что индексы и другие оптимизации не могут быть полезны для заказа. Я прав? И каков наилучший способ быстро получить упорядоченные данные? Возможно ли это в постгресе? Должен ли я использовать для этого другие инструменты? Может быть, ETL в нереляционной БД или что-то в этом роде?
пример простого запроса:
EXPLAIN ANALYZE SELECT * FROM offers WHERE offers.attributes -gt;gt; 'width' = '190' AND offers.attributes -gt;gt; 'height' = '55' AND offers.attributes -gt;gt; 'diameter' = '16' ORDER BY price
объясните, проанализируйте вывод:
Sort (cost=463529.78..463529.78 rows=1 width=248) (actual time=3083.447..3084.143 rows=12420 loops=1) Sort Key: price Sort Method: quicksort Memory: 6530kB -gt; Gather (cost=1000.00..463529.77 rows=1 width=248) (actual time=0.327..3078.755 rows=12420 loops=1) Workers Planned: 2 Workers Launched: 2 -gt; Parallel Seq Scan on offers (cost=0.00..462529.67 rows=1 width=248) (actual time=4.826..3072.672 rows=4140 loops=3) Filter: (((attributes -gt;gt; 'width'::text) = '190'::text) AND ((attributes -gt;gt; 'height'::text) = '55'::text) AND ((attributes -gt;gt; 'diameter'::text) = '16'::text)) Rows Removed by Filter: 3329193 Planning Time: 0.256 ms Execution Time: 3084.612 ms
все индексы таблиц
create index offers_attribu_5d15b4_gin on offers using gin (attributes); create index offers_created_ae6fa523 on offers (created); create index offers_updated_c723e738 on offers (updated); create index offers_quantity_dc0026a6 on offers (quantity); create index offers_model_id_8846a913 on offers (model_id); create index offers_price_list_id_1f3d95de on offers (price_list_id); create index offers_price_ids on offers (price); create index offers_model_price_idx on offers (model_id, price); create index offers_json_price_idx on offers (attributes, price); create index offers_json_model_idx on offers (attributes, model_id); create index offers_price_idx on offers (price);
Комментарии:
1. «Количество комбинаций фильтрации очень велико», но как насчет избирательности? Если одно условие устраняет 99,999% данных, а все остальные вместе взятые удаляют только 50% того, что осталось, вы можете в значительной степени игнорировать остальные условия.
2. @a_horse_with_no_name готово
3. @jjanes после фильтрации осталось около 100 тысяч строк
4. @jjanes, конечно, зависит от фильтров, например, может быть 10 000, но это все равно медленно
5. В вашем примере сортировка заняла гораздо меньше 1% от общего времени. Не стоит беспокоиться об этом.
Ответ №1:
Ваш запрос станет быстрее, если вы перепишете его так, чтобы он мог использовать индекс GIN в jsonb
столбце:
SELECT * FROM offers WHERE attributes @gt; '{ "width": 190, "height": 55, "diameter": 16 }' ORDER BY price;