Выборка с сортировкой
Добавлено: 19 дек 2009, 15:46
Есть у меня простая проблема, для которой я нашел только очень кривое решение:
есть таблица, в которой хранятся некоторые данные (на самом деле задача типовая), пусть будет такая:
table operations account integer,tm integer,...
данные по операциям клиентов в системе, клиент идентифицируется полем account, tm - время выполнения операции
созданы индексы
иногда мне надо получить список из последний операций клиента, отсортированных по времени, иногда - просто последнюю операцию или ее время
все это приводит к очевидному сканированию большого индекса и при неудачном раскладе запрос тормозит по полсекунды (запросов таких очень много)
вариант
приводит к тормозам в других случаях (если клиенты, у которых очень много операций, десятки тысяч)
в статистике - тысячи фетчей
Я сделал доп. поле:
acctm bigint
и при внесении данных в таблицу добавляю туда значение
account*1000000+tm
добавли индекс по нему
и все выборки по account= с сортировкой по tm первратил в
? - одинаковое значение номера аккаунта
это классно и предсказуемо работает (в статистике - всегда десятки фетчей), однако меня смущает 2 вещи:
1. заведено поле, которое мне нафиг не нужно (чисто функция двух других), однако вычисляемое поле для построения индекса не годится
2. запросы стали выглядеть безобразно
мне всегда казалось, что для таких случаев нужен индекс по двум полям:
с запросами вида
и все должно бы работать именно так, как мне хочется, однако для сортировки по tm этот индекс не используется, как бы мне не хотелось (перепробовал все, что в голову пришло)
есть у кого-нибудь мысли по оптимизации этого дела менее кривой, чем сделал я?
есть таблица, в которой хранятся некоторые данные (на самом деле задача типовая), пусть будет такая:
table operations account integer,tm integer,...
данные по операциям клиентов в системе, клиент идентифицируется полем account, tm - время выполнения операции
созданы индексы
Код: Выделить всё
create index operations_account on operations(account)
create descending index operations_tm on operations(tm)
Код: Выделить всё
select max(tm) from operations where account=?
вариант
Код: Выделить всё
select max(tm+0) from operations where account=?
в статистике - тысячи фетчей
Я сделал доп. поле:
acctm bigint
и при внесении данных в таблицу добавляю туда значение
account*1000000+tm
добавли индекс по нему
Код: Выделить всё
create descending index operations_acctm on operations(acctm)
Код: Выделить всё
select * from operations where acctm >= (? * 1000000) and acctm < ((? + 1) * 1000000) order by acctm desc
это классно и предсказуемо работает (в статистике - всегда десятки фетчей), однако меня смущает 2 вещи:
1. заведено поле, которое мне нафиг не нужно (чисто функция двух других), однако вычисляемое поле для построения индекса не годится
2. запросы стали выглядеть безобразно
мне всегда казалось, что для таких случаев нужен индекс по двум полям:
Код: Выделить всё
create descending index operations_account_tm on operations(account,tm)
Код: Выделить всё
select * from operations where account=? order by tm desc
есть у кого-нибудь мысли по оптимизации этого дела менее кривой, чем сделал я?