Как сгенерировать записи и распределить их по парам из таблицы? - PullRequest
2 голосов
/ 06 июня 2011

Мне нужно сгенерировать около миллиона случайных поездок между 40К пунктов назначения.Каждый пункт назначения имеет свой собственный вес (total_probability), чем он больше, тем больше поездок должно начинаться или заканчиваться в этом месте.

Либо поездки должны генерироваться случайным образом, но пункты назначения (начальная и конечная точки)должны быть взвешены по вероятности, или можно просто предварительно рассчитать точное количество поездок (разделить каждый вес на сумму весов, умножить на 1M и округлить до целых чисел).

Проблема в том, как сделать это в PostgreSQL без генерации таблицы 40K * 40K со всеми парами получателей.

          Table "public.dests"
   Column          |       Type       | Modifiers 
-------------------+------------------+-----------
 id                | integer          | 
 total_probability | double precision | 

          Table "public.trips"
   Column   |       Type       | Modifiers 
------------+------------------+-----------
 from_id    | integer          | 
 to_id      | integer          | 
 trips_num  | integer          | 
 ...
 some other metrics...

Первичный ключ для поездок - (from_id, to_id) Должен ли я генерировать таблицус 1M записей, а затем обновлять его итеративно, или цикл for с 1M вставками будет достаточно быстрым?Я работаю на 2-ядерном легком ноутбуке.

PS Я сдался и сделал это на Python.Чтобы выполнить набор запросов и преобразование в Python, я буду запускать сценарии SQL из Python, а не из сценария оболочки.Спасибо за предложения!

Ответы [ 2 ]

0 голосов
/ 06 июня 2011

В 9.1 вы можете использовать TRIGGER s на VIEW s, что эффективно позволяет вам создавать материализованные представления (хотя и вручную).Я думаю, что ваш первый запуск может быть дорогостоящим, но использование цикла - это, вероятно, путь, но потом после этого я бы использовал серию TRIGGER s для сохранения данных в таблице.

В конце дня вам нужно решить, хотите ли вы рассчитывать результаты для каждого запроса, или вы запоминаете результат с помощью материализованного представления.

0 голосов
/ 06 июня 2011

Я смущен вашим требованием, но, думаю, это поможет вам начать:

select 
    f.id as "from", t.id as to, 
    f.total_prob as from_prob, t.total_prob as to_prob
from 
    (
        select id, total_prob
        from dest
        order by random()
        limit 1010
    ) f
    inner join
    (
        select id, total_prob
        from dest
        order by random()
        limit 1010
    ) t on f.i != t.i
order by random()
limit 1000000
;

РЕДАКТИРОВАТЬ:

На моем не очень современном рабочем столе это заняло около десяти минут:

create table trips (from_id integer, to_id integer, trip_prob double precision);

insert into trips (from_id, to_id, trip_prob)
select 
    f.id, t.id, f.total_prob * t.total_prob
from 
    (
        select id, total_prob
        from dests
    ) f
    inner join
    (
        select id, total_prob
        from dests
    ) t on f.id != t.id
where random() <= f.total_prob * t.total_prob
order by random()
limit 1000000
;

alter table trips add primary key (from_id, to_id);

select * from trips limit 5;
 from_id | to_id |     trip_prob      
---------+-------+--------------------
       1 |     6 | 0.0728749980226821
       1 |    11 |  0.239824750923743
       1 |    14 |  0.235899211677577
       1 |    15 |  0.176168172647811
       1 |    17 |   0.19708509944588
(5 rows)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...