РедактироватьЛенивый заказ на /, где оценка
Кажется, что чистый материализации могут быть сохранены в качестве колонки на столе и индексироваться; Однако, мой конкретный случай использования (semver.satisfies
) требует более общего решения:
create table Submissions (
version text
created_at timestamp
)
create index Submissions_1 on Submissions (created_at)
Моего запрос будет выглядеть так:
select * from Submissions
where
created_at <= '2016-07-12' and
satisfies(version, '>=1.2.3 <4.5.6')
order by created_at desc
limit 1;
Где я не был бы в состоянии практически использовать ту же технику, запоминание ,
Оригинал
У меня есть таблица хранения текстовых данных и дат, на которых они были созданы:
create table Submissions (
content text,
created_at timestamp
);
create index Submissions_1 on Submissions (created_at);
Учитывая контрольную сумму и ссылочную дату, я хочу, чтобы получить последнюю Submission
где content
поля соответствует этой контрольной сумме:
select * from Submissions
where
created_at <= '2016-07-12' and
expensive_chksm(content) = '77ac76dc0d4622ba9aa795acafc05f1e'
order by created_at desc
limit 1;
Это работает, но я t очень медленно. Что Postgres заканчивает тем, что делает, принимая контрольную сумму каждой строки, а затем выполняя order by
:
Limit (cost=270834.18..270834.18 rows=1 width=32) (actual time=1132.898..1132.898 rows=1 loops=1)
-> Sort (cost=270834.18..271561.27 rows=290836 width=32) (actual time=1132.898..1132.898 rows=1 loops=1)
Sort Key: created_at DESC
Sort Method: top-N heapsort Memory: 25kB
-> Seq Scan on installation (cost=0.00..269380.00 rows=290836 width=32) (actual time=0.118..1129.961 rows=17305 loops=1)
Filter: created_at <= '2016-07-12' AND expensive_chksm(content) = '77ac76dc0d4622ba9aa795acafc05f1e'
Rows Removed by Filter: 982695
Planning time: 0.066 ms
Execution time: 1246.941 ms
Без order by
, это операция суб-миллисекунды, потому что Postgres знает, что я хочу только первый результат. Единственное различие заключается в том, что я хочу, чтобы Postgres начал поиск с последней даты вниз.
В идеале Postgres бы:
- фильтр
created_at
- сортировать по
created_at
, по убыванию- возвращение первой строки, где контрольная сумма соответствует
Я пытался писать запросы с встроенными представлениями, но explain analyze
показывает, что он будет просто переписан в то, что я уже имел выше.
Вы можете использовать нормальное сравнение и нормальный индекс, если вы храните его немного больше разумно, например, bigint '1000002000003' вместо' 1.2.3' и '4000005000006' вместо 4.5.6 (основной * 10^12 + минор * 10^6 + rel легкость). – Tometzky
Это хорошая идея, но semver действительно сложный. Я экспериментировал с несколькими подходами, и кажется, что то, что я сейчас пытаюсь сделать, дает лучший баланс точности результатов. Я уточнил вопрос, чтобы уточнить. – Synchronous
Может быть, чем использовать int [] -> [1,2,3]? Это также хороший показатель и лучше сравнивать? –