Самый быстрый способ подсчитать общее количество, а затем перечислить набор записей в MySQL - PullRequest
2 голосов
/ 14 октября 2009

У меня есть оператор SQL для выбора результатов из таблицы. Мне нужно знать общее количество найденных записей, а затем перечислить их подмножество (нумерация страниц).

Обычно я бы сделал 2 вызова SQL:

  1. один для подсчета общего количества записей (с помощью COUNT),
  2. другой для возврата подмножества (используя LIMIT).

Но, таким образом, вы действительно дублируете одну и ту же операцию на MySQL: операторы WHERE одинаковы в обоих вызовах.

Разве нет способа получить скорость, НЕ дублируя выбор на MySQL?

Ответы [ 7 ]

2 голосов
/ 14 октября 2009

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

1 голос
/ 14 октября 2009

Вы должны выполнить оба SQL-запроса, и COUNT выполняется очень быстро без предложения WHERE. Кэшируйте данные, где это возможно.

0 голосов
/ 14 октября 2009

Как уже отмечали другие, это, вероятно, не стоит большого беспокойства в этом случае - пока индексируется 'field', оба выбора будут очень быстрыми.

Если у вас есть (по какой-либо причине) ситуация, когда этого недостаточно, вы можете создать временную таблицу на основе памяти (то есть временную таблицу, поддерживаемую механизмом хранения памяти) и выбрать записи в эту временную таблицу. Тогда вы можете делать выборки из временной таблицы и быть вполне уверенными, что они будут быстрыми. Это может использовать много памяти, хотя (то есть это заставляет все данные оставаться в памяти на время), так что это довольно недружелюбно, если вы не уверены, что:

  1. Количество данных действительно мало;
  2. У вас так много памяти, что это не имеет значения; или
  3. В противном случае машина будет почти бездействовать.

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

0 голосов
/ 14 октября 2009

Если вы напишите свой запрос, включив в него один столбец, содержащий количество (в каждой строке), а затем остальные столбцы из второго запроса, вы можете:

  1. избегайте второго обхода базы данных (в любом случае, вероятно, дороже, чем ваш запрос)
  2. Увеличьте вероятность того, что парсер MySQL сгенерирует оптимизированный план выполнения, который повторно использует базовый запрос.
  3. Сделать операцию атомарной.

К сожалению, он также создает небольшое повторение, возвращая больше данных, чем вам действительно нужно. Но я ожидал бы, что это будет намного более эффективным в любом случае. Такую стратегию используют многие продукты ORM, когда они охотно загружают объекты из связанных таблиц с отношениями «многие к одному» или «многие ко многим».

0 голосов
/ 14 октября 2009

Вы можете попробовать выбрать только одно поле (скажем, идентификаторы) и посмотреть, поможет ли это, но я не думаю, что это поможет - я думаю, что самые большие издержки - это поиск MySQL правильных строк в первую очередь.

Если вы просто хотите посчитать общее количество строк во всей таблице (то есть без предложения WHERE), то я считаю, что SELECT COUNT(*) FROM table довольно эффективно.

В противном случае единственное решение, если вам нужно, чтобы общее количество было видно, - это выбрать все строки. Однако вы можете кэшировать это в другой таблице. Если вы выбираете что-то из категории, скажем, сохраните UID категории и общее количество выбранных строк. Затем всякий раз, когда вы добавляете / удаляете строки, снова подсчитываете итоги.

Другой вариант - хотя он может немного пожертвовать удобством использования - это выбрать только строки, необходимые для текущей страницы и следующей страницы. Если для следующей страницы доступно несколько строк, добавьте ссылку «Далее». Сделайте то же самое для предыдущей страницы. Если у вас есть 20 строк на страницу, вы выбираете не более 60 строк при каждой загрузке страницы, и вам не нужно считать все доступные строки.

0 голосов
/ 14 октября 2009

Если вы действительно не хотите запускать запрос COUNT() - и, как говорили другие, это не то, что существенно замедляет ход событий, - тогда вы должны принять решение о размере чанка (т.е. LIMIT число) впереди. Это спасет вас от запроса COUNT(), но вы можете получить неудачные результаты разбивки на страницы (например, на 2 страницах, где на 2-й странице есть только 1 результат).

Итак, быстрая COUNT(), а затем разумная LIMIT установка или отсутствие COUNT() и произвольный LIMIT, который может увеличить количество более дорогих запросов, которые вам нужно сделать.

0 голосов
/ 14 октября 2009

Вы должны просто запустить COUNT один раз, а затем кэшировать его где-нибудь. Затем вы можете просто выполнить запрос нумерации страниц.

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