Есть ли замена COUNT?

jsmth
Дата: 06.11.2008 15:19:24
Задача - организовать постраничный вывод. Для этого требуется знать количество строк в выборке.
Вариант
SELECT * FROM (
SELECT row_number() over (order by ....) rn, COUNT(*) over () cnt, .... FROM ...
) WHERE rn BETWEEN 1 AND 20
ORDER BY rn
Призводительность - больше секунды.

Без аналитического COUNT запрос работает более чем в два раза быстрее (0.5 сек). В чем фундаментальная причина? Сортировка так не замедляет запрос..
А как еще выкрутится - в голову не приходит.

Попробовал убрать COUNT и написать что-то вроде
SELECT Q.*, max(Q.rn) over () cnt FROM (
SELECT * FROM (
SELECT row_number() over (order by ....) rn, .... FROM ...
) WHERE rn BETWEEN 1 AND 20
)
ORDER BY rn

- производительность все такая же низкая - больше секунды.
expla
Дата: 06.11.2008 15:24:04
Для начала планы запросов сравни.
Andrey.L
Дата: 06.11.2008 15:24:52
jsmth,
FAQ
jsmth
Дата: 06.11.2008 15:25:47
Andrey.L,
И что? Постраничный вывод и так есть. Вопрос был про размер выборки
jsmth
Дата: 06.11.2008 15:29:05
expla, планы различаются одной строкой:

с COUNT(*)
SORT ORDER BY
VIEW
WINDOW SORT
без COUNT(*)
SORT ORDER BY
VIEW
WINDOW SORT PUSHED RANK
expla
Дата: 06.11.2008 15:36:02
jsmth
expla, планы различаются одной строкой:


Ну наверное в том собака и порылась... Я так понимаю, count over должен посчитать все строки в таблице, так что размер страницы ему ни как не помогает, тогда как всё остальное ограничивается размером страницы. Как только страница получена, вычисления прекращаются.
jsmth
Дата: 06.11.2008 15:41:30
expla, Нет, не прекращаются. Потому как идет получение полного результирующего множества, потом его полная сортировка и лишь потом выдача нужной порции (страницы)
jsmth
Дата: 06.11.2008 15:42:04
В том-то и весь фикус... все равно все множество чесать из-за сортировки
expla
Дата: 06.11.2008 16:03:47
jsmth
expla, Нет, не прекращаются. Потому как идет получение полного результирующего множества, потом его полная сортировка и лишь потом выдача нужной порции (страницы)


Сортировка на ограниченном, тем более на таком маленьком, буфере будет быстрее, чем полная сортировка, особенно если для сохранения промежуточных результатов полной сортировки нужно использовать диски.
jsmth
Дата: 06.11.2008 16:27:05
Нашел решение.

WITH Q AS (
исходный запрос
)
SELECT * FROM (
SELECT row_number() over (order by ....) rn, (SELECT COUNT(*) FROM Q) cnt, Q.*
FROM Q
) WHERE rn BETWEEN 1 AND 20
ORDER BY rn

На удивление работает за 0.6 сек.