выберите топ 1000, но знаете, сколько там строк? - PullRequest
3 голосов
/ 22 декабря 2008

SQL Server 2005

У меня есть 10 миллионов строк в БД, и я запускаю выбор (с большим количеством "где" и соединений ... довольно сложный). Результаты представлены в сетке (например, результаты goolge), и поэтому пользователь не может использовать более 1000 результатов.

Так что я ограничиваю свой SQL ТОП 1000.

Проблема : Пользователь по-прежнему хочет знать, что для его поиска найдено 5432 результатов.

Могу ли я получить эту информацию, не заплатив цену (или, другими словами, все еще получая преимущества в скорости, которые дает мне «топ-1000»?)

Предположения - Предположим, что TOP 1000 приносит 1000 из 100K строк. Так что даже сетевая цена перемещения 100K может быть проблемой.

Выводы Там нет бесплатного обеда! Вы можете получить элегантный способ (принятый ответ), но он по-прежнему занимает больше времени, чем более дорогая операция (то есть подсчет всех результатов). В реальной жизни я воспользуюсь подходом 2 SQL: один возвращает первые 1000 строк для отображения, а другой - ASYNC и обновляет некоторую панель AJAX с результатами count (*), которые будут намного дольше работать на компьютере

Ответы [ 6 ]

10 голосов
/ 22 декабря 2008
SELECT TOP 1000 x, y, z, COUNT(*) OVER () AS TotalCount
FROM dbo.table
5 голосов
/ 22 декабря 2008

Лично я бы выбрал два утверждения, попадающих в базу данных. Один для получения количества, один для получения первых 1000 записей.

Вы можете выполнить оба запроса в пакете, чтобы немного повысить производительность, сохранив информацию из базы данных.

-- Get the count
select count(*) from table where [criteria]

-- Get the data
select [cols] from table where [criteria]
3 голосов
/ 22 декабря 2008

Вы хотите использовать "count" и группировать по, проверьте эту ссылку: http://msdn.microsoft.com/en-us/library/ms175997.aspx

Также ваша проблема, кажется, опубликована здесь: http://www.eggheadcafe.com/software/aspnet/32427870/select-top-n-plus-a-count.aspx

Удачи

0 голосов
/ 22 декабря 2008

Это не ответит на ваши вопросы, но я думаю, что это хороший случай, когда мы реализуем:

  • Аппаратное обеспечение дешево
  • Программисты не дешевы

Правило.

Да, выполнение двух запросов (один счетчик, один выбор *) не является оптимальным решением (это можно сделать одним запросом!). Но как уверен как вы думаете, что это будет узким местом?

Я застрял на этих вопросах, и я должен помнить это сам, чтобы продолжить развитие.

Пишите быстро, пишите лучше, ПРОФИЛЬ, затем пишите лучше.

Или, может быть, это является узким местом, и поэтому вы спрашиваете. Но мне кажется, что если бы это было вашим узким местом, лучшей оптимизацией была бы реструктуризация базы данных, чтобы упростить сам запрос.

0 голосов
/ 22 декабря 2008

Поскольку вы используете SQL Server 2005, вы можете использовать CTE для этого типа запроса. Вот что я сейчас делаю для клиента:

;WITH Search_Results AS
(
     SELECT TOP(@system_max_rows)
          my_column1,
          my_column2,
          ROW_NUMBER() OVER
          (
               ORDER BY
                    -- Your order criteria here
          ) AS row_num,
          COUNT(my_column1) OVER (PARTITION BY '') As total_count
     FROM
          My_Table
     -- Put any joins here
     WHERE
          -- Put WHERE criteria here
)
SELECT
     my_column1,
     my_column2,
     row_num,
     total_count
FROM
     Search_Results
WHERE
     ((row_num - 1)/@rows_per_page) + 1 = CASE
                WHEN ((total_count - 1)/@rows_per_page) + 1 < @page_number THEN ((total_count - 1)/@rows_per_page) + 1
                ELSE @page_number
           END
OPTION (RECOMPILE)

Произошла перекомпиляция, поскольку критерии поиска могут резко меняться между вызовами хранимой процедуры, что ухудшает план запроса в кэше. Надеемся, что параметры / переменные очевидны. Это было для поискового решения. Системная переменная max lines является жестко запрограммированной, поэтому даже приложение не может переопределить максимальное количество строк, которые могут быть возвращены, и вызвать сбой сервера. Чтобы получить топ 1000, вы должны передать @page_number = 1 и @rows_per_page = 1000.

0 голосов
/ 22 декабря 2008

Возможно, вы переоцениваете выигрыш в производительности "топ-1000", особенно если будет всего ~ 5000 общих результатов.

Сервер уже должен выполнить все объединения и прочее (что обычно является сложной частью), а затем должен упорядочить набор результатов так, как вы указали, ПОТОМ наконец получает 1000 первых результатов.

Два варианта здесь:

1) Выполните один запрос с помощью счетчика (*), чтобы получить счетчик результатов, а затем выполните второй запрос с вашей первой 1000, получив соответствующие столбцы (как предлагает Нейл). ИЛИ
2) Получить все строки в первый раз, кэшировать их в наборе результатов, а затем отображать только 1000 строк для пользователя.

Может показаться, что первый будет быстрее, но второй должен попасть в базу данных только один раз, и, в зависимости от особенностей вашей базы данных и запроса, может быть лучше (если база данных не вернется 100 000 строк!)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...