Оптимизация запроса. Номер записи в таблице.

Jeneckiy
Дата: 20.02.2013 14:44:21
Ситуация следующая:
Есть табличка
Id Rating
1 3000
1405832 2999
2 2999
89734 2998
...............
387462 1


Вот таких вот записей может быть миллионов 10. Rating - индекс order desc. Rating изменяется в пределах от 1 до 3000.
Задача - вытащить позицию записи по Id.

Есть запрос
SELECT position FROM (SELECT position = ROW_NUMBER() OVER (ORDER BY Rating DESC), t.Id FROM table 1) t1 WHERE t1.Id=@id

Но даже при 2млн. записей работает медленно. Можно ли как-то обойтись без ORDER BY? Может я чего-то не понимаю, но она же и так отсортирована. каким способом еще можно вытащить номер записи?
Думал может дополнительное поле создать в табличке "position" но как его обновлять шустро тоже не пойму(

Help!
hpv
Дата: 20.02.2013 15:19:01
Jeneckiy,

Здравствуйте.
Для начала приведите реальный план вашего запроса.
Jeneckiy
Дата: 20.02.2013 15:42:27
hpv,

а чем этот не реальный?

SELECT position FROM (SELECT position = ROW_NUMBER() OVER (ORDER BY Rating DESC), t.Id FROM table 1) t1 WHERE t1.Id=1


результат = 1

SELECT position FROM (SELECT position = ROW_NUMBER() OVER (ORDER BY Rating DESC), t.Id FROM table 1) t1 WHERE t1.Id=1405832


результат = 2

в дальнейшем допустим произошли изменения
update table set Rating=3000 where Id=89734


SELECT position FROM (SELECT position = ROW_NUMBER() OVER (ORDER BY Rating DESC), t.Id FROM table 1) t1 WHERE t1.Id=89734


результат = 2
Мистер Хенки
Дата: 20.02.2013 15:51:20
Jeneckiy,
так не на тему оптимизации, но выходит что у записей с одинаковым рейтингом разная позиция И как определяется эта позиция не важно (среди записей с одинаковым рейтингом)?
Jeneckiy
Дата: 20.02.2013 15:57:05
Мистер Хенки,

Позиция с одинаковым рейтингом определяется по принципу "чем меньше id - тем ты круче") да, табличку примера заполнил калечно id 1405832 должен быть на третей позиции изначально,а id 2 на второй.
Гость333
Дата: 20.02.2013 15:57:20
Jeneckiy
Есть запрос
SELECT position FROM (SELECT position = ROW_NUMBER() OVER (ORDER BY Rating DESC), t.Id FROM table 1) t1 WHERE t1.Id=@id

Не смущает, что этот запрос может на одних и тех же данных возвращать разный результат?
"ROW_NUMBER() OVER (ORDER BY Rating DESC)" — у вас ведь, судя по описанию, тысячи записей с одним и тем же рейтингом — и в пределах этого рейтинга row_number() может вычисляться произвольным образом. Я смоделировал вашу ситуацию, и для одной и той же записи запрос возвращает то 253571, то 253580, то 253828...

Jeneckiy
она же и так отсортирована

Отсортирована, но порядковый номер (row_number) никоим образом нигде не хранится. Поэтому он каждый раз вычисляется.
Гость333
Дата: 20.02.2013 16:02:08
Jeneckiy
Позиция с одинаковым рейтингом определяется по принципу "чем меньше id - тем ты круче")

То есть запрос выглядит так?
SELECT position FROM (SELECT position = ROW_NUMBER() OVER (ORDER BY Rating DESC, t.Id), t.Id FROM table t) t1 WHERE t1.Id=@id
?
В любом случае, не надо ожидать, что row_number для вашего запроса хранится где-то в индексе.
Мистер Хенки
Дата: 20.02.2013 16:02:27
Jeneckiy
Мистер Хенки,

Позиция с одинаковым рейтингом определяется по принципу "чем меньше id - тем ты круче") да, табличку примера заполнил калечно id 1405832 должен быть на третей позиции изначально,а id 2 на второй.

ну в вашем запросе такого нет если что. иначе было бы position = ROW_NUMBER() OVER (ORDER BY Rating DESC,id asc) . Ну и индекс тогда бы соответствующий строить
count(*)
Дата: 20.02.2013 16:34:03
declare @id int 
declare @r int


select @r = rating from table where id = ID
select position = (
(SELECT count(*) from table  where Rating  > @r) + (SELECT count(*) from table  where Rating  = @r and id < @id)
)

+ индекс Rating desc, id asc
Jeneckiy
Дата: 20.02.2013 16:35:33
Гость333,

Поле Id является первичным ключом, и отсортировано asc. Поэтому значение позиции всегда одно(отклонение в 1 позицию допускается). Простите не сказал сразу.

Гость333
Отсортирована, но порядковый номер (row_number) никоим образом нигде не хранится. Поэтому он каждый раз вычисляется.
Вот жаль,что не хранится... Как тогда быть? Смотрю в сторону секционирования. Думаю наделать 20 табличек, запрос оставить тот же, но с учетом номера таблицы. Но не уверен,что мне это поможет, тк при изменении рейтинга выходящей за пределы одной таблицы необходимо выполнять 2 DML запроса(delete,insert), причем в разных таблицах..
Есть еще какие варианты?