Я думаю, что хорошей идеей также является сохранение номера зарегистрированного пользователя на вашем сайте (или количества сообщений на форуме, записей в блогах, любого числа, которое вам нужно получить count(*)
) в качестве счетчика в отдельном счетчике.table and increment - уменьшает счетчик всякий раз, когда пользователь регистрирует себя / отменяет себя с веб-сайта (например, с помощью триггеров).
COUNT (*)
запросов могут быть довольно тяжелыми и, таким образом, вместо count(*)
вымог бы сделать select counter from counter_table
, что является довольно непосредственным* Агрегатная функция COUNT () и способы оптимизации запросов, использующих ее, вероятно, входят в десятку самых неправильно понимаемых тем в MySQL.Вы можете выполнить поиск в Интернете и найти больше дезинформации по этой теме, чем мы думаем.Прежде чем мы перейдем к оптимизации, важно понять, что на самом деле делает COUNT ().
Что делает COUNT ()
COUNT () - это специальная функция, которая работает двумя совершенно разными способами:он считает значения и строки.Значение является ненулевым выражением (NULL - это отсутствие значения).Если вы указываете имя столбца или другое выражение в скобках, COUNT () подсчитывает, сколько раз это выражение имеет значение.Это сбивает с толку многих людей, отчасти потому, что значения и NULL сбивают с толку.Если вам нужно узнать, как это работает в SQL, мы предлагаем хорошую книгу по основам SQL.(Интернет также не обязательно является хорошим источником точной информации по этой теме.) Другая форма COUNT () просто подсчитывает количество строк в результате.Это то, что делает MySQL, когда знает, что выражение внутри скобок никогда не может быть NULL.Наиболее очевидным примером является COUNT (*), который представляет собой специальную форму COUNT (), которая не расширяет подстановочный знак * до полного списка столбцов в таблице, как вы могли бы ожидать;вместо этого он полностью игнорирует столбцы и считает строки.Одна из наиболее распространенных ошибок, которые мы видим, - это указание имен столбцов в скобках, когда вы хотите посчитать строки.Если вы хотите узнать количество строк в результате, вы всегда должны использовать COUNT (*).Это четко сообщает о ваших намерениях и позволяет избежать низкой производительности.
Мифы о MyISAM
Распространенным заблуждением является то, что MyISAM чрезвычайно быстр для запросов COUNT ().Это быстро, но только для очень особого случая: COUNT () без предложения WHERE, которое просто подсчитывает количество строк во всей таблице.MySQL может оптимизировать это, потому что механизм хранения всегда знает, сколько строк в таблице.Если MySQL знает, что col никогда не может быть NULL, он также может оптимизировать выражение COUNT (col), преобразовав его в COUNT () для внутреннего использования.MyISAM не имеет никаких волшебных оптимизаций скорости для подсчета строк, когда в запросе есть предложение WHERE, или для более общего случая подсчета значений вместо строк.Это может быть быстрее, чем другие механизмы хранения для данного запроса, или это может быть не так.Это зависит от множества факторов.
Простые оптимизации
Иногда вы можете использовать оптимизацию COUNT () MyISAM, когда вы хотите сосчитать все, кроме очень небольшого количества строк.которые хорошо проиндексированы.В следующем примере используется стандартная база данных World, чтобы показать, как можно эффективно найти количество городов, чей ID больше 5. Вы можете написать этот запрос следующим образом: mysql> SELECT COUNT () FROM world.City WHERE ID>5;Если вы профилируете этот запрос с помощью SHOW STATUS, вы увидите, что он сканирует 4079 строк.Если вы отменяете условия и вычитаете количество городов, чьи идентификаторы меньше или равны 5, из общего числа городов, вы можете уменьшить его до пяти строк: mysql> SELECT (SELECT COUNT () FROMworld.City) - COUNT () -> ОТ world.City WHERE ID <= 5;Эта версия читает меньше строк, потому что подзапрос превращается в константу на этапе оптимизации запроса, как вы можете увидеть с помощью EXPLAIN: ... + ------ + ------------------------------ + |id |select_type |стол | ... |строки |Extra |... + ------ + ------------------------------ + |1 |ПЕРВИЧНЫЙ |Город | ... |6 |Используя где;Используя индекс ||2 |SUBQUERY |NULL | ... |NULL |Выберите таблицы оптимизированы прочь |... + ------ + ------------------------------ + Частый вопрос о списках рассылки и IRCКаналы - это то, как получить счетчики для нескольких различных значений в одном столбце одним запросом, чтобы уменьшить количество требуемых запросов.Например, скажем, вы хотите создать один запрос, который подсчитывает, сколько элементов имеют каждый из нескольких цветов.Вы не можете использовать ИЛИ (например, ВЫБЕРИТЕ СЧЕТЧИК (color = 'blue' ИЛИ color = 'red') FROM items;), потому что это не разделит различные значения для разных цветов.И вы не можете поместить цвета в предложении WHERE (например, SELECT COUNT (*) FROM элементов WHERE color = 'blue' и color = 'red';), потому что цвета являются взаимоисключающими.Вот запрос, который решает эту проблему: mysql> SELECT SUM (IF (color = 'blue', 1, 0)) AS blue, SUM (IF (color = 'red', 1, 0)) -> AS red FROMПредметы;А вот другой эквивалентный, но вместо использования SUM () используется COUNT () и гарантирует, что выражения не будут иметь значений при ложных критериях: mysql> SELECT COUNT (color = 'blue' OR NULL) AS blue,COUNT (color = 'red' ИЛИ NULL) -> КАК красный ОТ элементов;
Более сложные оптимизации
В общем, запросы COUNT () сложно оптимизировать, так как обычно им нужно подсчитатьмного строк (то есть доступ к большому количеству данных).Единственный другой способ оптимизации внутри самого MySQL - это использование индекса покрытия, который мы обсуждали в главе 3. Если это не поможет, вам нужно внести изменения в архитектуру вашего приложения.Рассмотрим сводные таблицы (также описанные в главе 3) и, возможно, внешнюю систему кэширования, такую как memcached.Вы, вероятно, окажетесь перед знакомой дилеммой: «Быстро, точно и просто: выберите любые два».