2012-05-30 4 views
2

Следующий запрос занимает около 300-400 мс на postgresql 9.1. Таблица содержит ~ 2M строк. Является ли это оправданным? Можно ли улучшить?postgresql fetch 100 случайных строк

SELECT "Products"."Id" 
     , "Products"."Title" 
     , "Products"."ThumbHeight" 
     , "Products"."LargeImageWidth" 
     , "Products"."LargeImageHeight" 
     , "Products"."Url" 
     , "Products"."BrowseNodeId" 
FROM "Products" 
WHERE "Products"."Id" = ANY(ARRAY(SELECT (random()*2233071)::int 
       FROM generate_series(1, 100))); 

А вот объяснить план:

-------------------------------------------------------------------------------- 
Bitmap Heap Scan on "Products" (cost=60.48..100.46 rows=10 width=268) 
    Recheck Cond: ("Id" = ANY ($0)) 
    InitPlan 1 (returns $0) 
    -> Function Scan on generate_series (cost=0.00..17.50 rows=1000 width=0) 
    -> Bitmap Index Scan on "Products_pkey" (cost=0.00..42.97 rows=10 width=0) 
    Index Cond: ("Id" = ANY ($0)) 

Поясните анализ:

Bitmap Heap Scan on "Products" (cost=60.48..100.46 rows=10 width=268) (actual time=77.702..80.944 rows=100 loops=1) 
    Recheck Cond: ("Id" = ANY ($0)) 
    InitPlan 1 (returns $0) 
    -> Function Scan on generate_series (cost=0.00..17.50 rows=1000 width=0) (actual time=0.097..0.348 rows=100 loops=1) 
    -> Bitmap Index Scan on "Products_pkey" (cost=0.00..42.97 rows=10 width=0) (actual time=77.601..77.601 rows=104 loops=1) 
     Index Cond: ("Id" = ANY ($0)) 
Total runtime: 81.409 ms 

Id является первичным ключом: "Products_pkey" PRIMARY KEY, btree ("Id")

Спасибо!

ответ

0

Вот решение, которое хорошо подходит для моего случая использования (выбрать 100 случайных продуктов для веб-страницы):

  1. Дублировать таблицу
  2. Перемешать строки таблицы
  3. Добавить авто инкремент колонки
  4. Выбрать из случайного диапазона (Например 100-200, 1567000-1567100)

время запроса пошел вниз под 2мс.

Вот набор команд я использовал:

create table RandProducts as select * from "Products" order by random(); 
alter table RandProducts add column RandId serial8; 
create index on RandProducts(randid); 

А затем, чтобы получить 100 случайных строк я просто сделать что-то вроде этого:

select * from Products where RandId between 8000 and 8100; 
1

Попробуйте это по сравнению с запросом:

SELECT "Products"."Id" 
     , "Products"."Title" 
     , "Products"."ThumbHeight" 
     , "Products"."LargeImageWidth" 
     , "Products"."LargeImageHeight" 
     , "Products"."Url" 
     , "Products"."BrowseNodeId" 
FROM "Products" 
ORDER BY random() 
LIMIT 100 
+0

Время: 24109.466 мс – michaelr524

+1

Это наихудшее решение, когда вы ищете производительность, особенно для больших таблиц. – michaelr524

Смежные вопросы