Какая быстрая база данных для интернет-магазина с более чем 50 тысячами товаров и поиском?

День добрый!

Пишу проект на Django, интернет-магазин с большим каталогом, товаров от 50 тысяч. Поиск будет осуществляться по множеству параметров.

Сейчас используется структура для поиска в виде массива в postgres, с поиском по нему. Сам поиск, в принципе, осуществляется быстро, но вот вывод доступных вариантов для поиска собирается очень долго.

Пример - яндекс-маркет. Ткнул на телефоны – он их вывел, а справа все доступные варианты параметров.
Использую redis для кеширования, но как смешно не звучало – от этого только хуже, редис не предназначен для кеширования больших объектов.

Есть идеи?

У меня не используется EAV. Я выбираю товары по типу tags @> ['param1', 'param2', 'param3']
Параметры дополнительные для уточнения поиска выбираются
SELECT unnest(tags) FROM items WHERE tags @> ['param1', 'param2', 'param3'] GROUP BY 1

Оперативной памяти 24 гб. Параметров поиска от 1 до 6 сразу. Чем больше параметров сразу указывает юзер, тем быстрее все ищется. ManyToMany плохо потому что у параметра "диаметр", к примеру, может быть сразу 10-15 значений. Если я хочу найти товар, у которого есть диаметр 10, 11, 12 – это делает join на каждый из диаметров, что очень тормозит систему.

Всему виной был redis и список в более чем миллион элементов в нем. Недоглядел, но положительные плоды есть – товары без всяких кешей отгружаются за 350-400 мс вместе с доступными фильтрами и 200-250 без фильтров, только товары.

Есть перспективы ускорения еще больше?)
Всем страждущим – solr + facets и будет вам счастье, поиск неимоверно быстрый.
  • Вопрос задан
  • 4799 просмотров
Решения вопроса 2
Vakiliy
@Vakiliy
Сделайте вложенный запрос перед использованием unnest,
Вложенный запрос
explain (analyze) select unnest(tags) from (SELECT tags FROM t5 WHERE tags @> array['param-1'] group by 1) as t group by 1;
                                                          QUERY PLAN                                                           
-------------------------------------------------------------------------------------------------------------------------------
 HashAggregate  (cost=14655.30..14660.38 rows=1000 width=84) (actual time=490.721..490.722 rows=10 loops=1)
   ->  Subquery Scan on t  (cost=14647.62..14652.80 rows=1000 width=84) (actual time=490.690..490.706 rows=55 loops=1)
         ->  HashAggregate  (cost=14647.62..14647.73 rows=10 width=84) (actual time=490.676..490.676 rows=10 loops=1)
               ->  Seq Scan on t5  (cost=0.00..13459.00 rows=475450 width=84) (actual time=0.033..181.649 rows=475324 loops=1)
                     Filter: (tags @> '{param-1}'::text[])
                     Rows Removed by Filter: 24676
 Total runtime: 490.843 ms
(7 rows)

Исходный
explain (analyze) SELECT unnest(tags) FROM t5 WHERE tags @> array['param-1'] group by 1;
                                                      QUERY PLAN                                                       
-----------------------------------------------------------------------------------------------------------------------
 HashAggregate  (cost=368857.88..368862.95 rows=1000 width=84) (actual time=1196.758..1196.759 rows=10 loops=1)
   ->  Seq Scan on t5  (cost=0.00..249995.38 rows=47545000 width=84) (actual time=0.020..680.547 rows=2501231 loops=1)
         Filter: (tags @> '{param-1}'::text[])
         Rows Removed by Filter: 24676
 Total runtime: 1196.790 ms
(5 rows)

Вложенный с seqscan off

с set enable_seqscan to off;
explain (analyze) select unnest(tags) from (SELECT tags FROM t5 WHERE tags @> array['param-1'] group by 1) as t group by 1;
                                                                      QUERY PLAN                                                                      
------------------------------------------------------------------------------------------------------------------------------------------------------
 HashAggregate  (cost=19433.16..19438.24 rows=1000 width=84) (actual time=411.248..411.249 rows=10 loops=1)
   ->  Subquery Scan on t  (cost=19425.49..19430.66 rows=1000 width=84) (actual time=411.220..411.233 rows=55 loops=1)
         ->  HashAggregate  (cost=19425.49..19425.59 rows=10 width=84) (actual time=411.205..411.206 rows=10 loops=1)
               ->  Bitmap Heap Scan on t5  (cost=5084.74..18236.86 rows=475450 width=84) (actual time=74.696..126.809 rows=475324 loops=1)
                     Recheck Cond: (tags @> '{param-1}'::text[])
                     ->  Bitmap Index Scan on t5_tagx_gist  (cost=0.00..4965.87 rows=475450 width=0) (actual time=73.514..73.514 rows=475324 loops=1)
                           Index Cond: (tags @> '{param-1}'::text[])
 Total runtime: 411.337 ms
(8 rows)

исходные данные:
create table t5 as (select i id, rand_array() tags from generate_series(1,500000) as i);
create index t5_tagx_gin on t5 using gin (tags);

create or replace function rand_array() returns text[][] as $$
begin
 return (select array_agg(t1.col1) from (select format('param-%s', i) col1 from generate_series(1,rand(10)) as i) as t1);
end;
$$ language 'plpgsql' strict;


ЗЫ, i5 2410M 8gb, PostgreSQL 9.3.4 on x86_64-unknown-linux-gnu
Ответ написан
opium
@opium
Просто люблю качественно работать
поиск перенести на выбор в сфинкс, эластик серч, солр
и будет больше счаться
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
FacedSID
@FacedSID
Не знаю чем вам EAV не угодила. У меня база значений по каждому полю лежит в разных таблицах. Когда происходит выборка по одному параметру, то подключается именно та таблица, которая отвечает за конкретный параметр. Получается, что при поиске по трем параметрам подключается например три таблицы суммарный объем которых составляет 3000 записей, а не одна таблица в которой около 200 000 записей (причем по несколько раз на каждый параметр) и это вполне приемлимо + кеширование SQL запросов и самих объектов в apc.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы