Выбор подкачки, в базе данных или в веб-приложении - PullRequest
2 голосов
/ 27 мая 2011

Я стремлюсь к тому, чтобы страницы отчетов нашего веб-сайта были переработаны быстрее, и я стою на пороге того, как мне следует реализовать пейджинг.Наша база данных велика,> 150 миллионов записей.В большинстве наших отчетов требуются сложные данные из 5-10 таблиц, поэтому в каждой из них может быть 5 или 6 объединений и некоторые внутренние выборки.Очевидно, что это не быстрые запросы.

Чтобы реализовать разбиение на страницы на стороне базы данных, для каждого веб-запроса мне нужно запросить в базе данных строки для текущей страницы (скажем, 100 из 10000), но я такжепридется запросить базу данных снова, чтобы получить общее количество возможных строк.В результате я, по сути, выполняю весь запрос дважды, потому что запрос, чтобы получить общее количество записей, все равно должен будет выполнить все объединения и внутренние операции выбора, чтобы определить общее количество.

Не будет ли лучшевыполнить запрос один раз, вернуть все результаты, кэшировать его в сеансе и распечатать с помощью веб-кода?Я знаю, что первоначально извлекаю больше данных, но я только запускаю запрос, который может занять 30 - 60 секунд один раз вместо двух.

Это своего рода общий вопрос технологии, но в случае, если он имеет значение, яЯ использую .net 4.0 и Oracle 11g.

Ответы [ 3 ]

3 голосов
/ 27 мая 2011

Исходя из моего опыта, пейджинг всегда быстрее, если оставить его в базе данных.В конце концов, база данных создана для запроса и манипулирования огромными объемами данных.

Если вы возвращаете большие объемы данных в .NET и «кэшируете» их в сеансе, у вас быстро заканчивается память на вашем сервере.

3 голосов
/ 27 мая 2011

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

SELECT [cols], nb_rows
  FROM (SELECT [cols], nb_rows, rownum r
          FROM (SELECT [cols], count(*) over() nb_rows
                  FROM [your_query])
         WHERE rownum <= :M)
 WHERE r >= :N

Это позволит вам выполнить запрос только один раз и будет менее напряженным для вашей сети.bandwidth.

Для дальнейшего анализа см. Скорость разбиваемых запросов в Oracle .

Кэширование результата всего запроса может иметь смысл, если:

  • Пользователи регулярно перемещаются вперед / назад по набору результатов без необходимости обновления данных.
  • Пропускная способность сети и доступная память (на стороне приложения) достаточны (скорее всего, это будет возможно только при одновременном количестве одновременныхколичество пользователей ограничено)
1 голос
/ 27 мая 2011

Сделай это в БД.Для Oracle вы можете попробовать что-то вроде:

select * 
  from ( select a.*, rownum r 
           from ( select *
                    from t
                   where x = :host_variable
                   order by y ) a
          where rownum <= :HigherBound )
 where r >= :LowerBound

, где LowerBound и HigherBound определяют границы вашей страницы (для страницы 1, показывающей 10 на страницу, у вас будет меньше = 1 и выше = 10)

Хитрость здесь в следующем:

  1. Убедитесь, что ваш внутренний выбор с помощью order by достаточно быстр (использует правильные индексы).
  2. Использование rownum позволяет Oracle использовать клавишу остановки,помогает ограничить число строк, которые необходимо обработать.

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

...