Я считаю, что многие люди знакомы с запросом к базе данных, и все часто высмеивают, что программисты являются специалистами по CRUD, так называемому CRUD, имеющему в виду добавление, удаление, модификацию и проверку базы данных.
В операциях добавления, удаления, модификации и запроса к базе данных наиболее часто используемой операцией запроса является операция запроса. Во всех операциях запроса часто используется операция подсчета.
Что касается статистики количества строк в базе данных, будь то MySQL или Oracle, можно использовать функцию COUNT.
Однако даже эта часто используемая функция COUNT скрывает много загадок, особенно во время интервью, если вы не будете осторожны, вас будут оскорблять. Если вы мне не верите, попробуйте ответить на следующие вопросы:
1. Сколько использований COUNT?
2. В чем разница между результатами запроса COUNT(имя поля) и COUNT(*)?
3. В чем разница между COUNT(1) и COUNT(*)?
4. Что более эффективно между COUNT(1) и COUNT(*)?
5. Почему «Руководство по разработке Java для Alibaba» рекомендует использовать COUNT(*)
6. Какие оптимизации выполняет движок MySQL MyISAM для COUNT(*)?
7. Какие оптимизации выполняет движок MySQL InnoDB для COUNT(*)?
8. Что является ключевой предпосылкой оптимизации COUNT(*) с помощью MySQL, упомянутой выше?
9. Когда SELECT COUNT(*), есть ли разница между добавлением или отсутствием добавления условия where?
10. Каков процесс выполнения COUNT(*), COUNT(1) и COUNT(имя поля)?
Если вы можете точно ответить на все вышеперечисленные 10 вопросов, это означает, что вы действительно понимаете функцию COUNT. Если есть какие-то моменты, которые вы не понимаете, эта статья может помочь вам ответить на ваши вопросы.
Знакомьтесь: COUNT
Что касается функции COUNT, на официальном сайте MySQL есть подробное введение:
Просто переведите:
1. COUNT(expr) возвращает количество строк, извлеченных оператором SELECT, где значение expr не равно NULL. Результатом является значение BIGINT.
2. Если результат запроса не соответствует ни одной записи, вернуть 0
3. Однако стоит отметить, чтоCOUNT(*)
Результат статистики будет включать количество строк со значением NULL.
То есть следующие записи таблицы
create table #bla(id int,id2 int)
insert #bla values(null,null)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,1)
insert #bla values(1,null)
insert #bla values(null,null)
Используя операторы count(*), count(id), count(id2), результаты запроса следующие:
select count(*),count(id),count(id2)
from #bla
results 7 3 2
КромеCOUNT(id)
иCOUNT(*)
Кроме того, вы также можете использоватьCOUNT(常量)
(какCOUNT(1)
) для подсчета количества строк, то в чем разница между этими тремя операторами SQL? Что эффективнее? Почему в «Руководстве по разработке Java для Alibaba» обязательно не использоватьCOUNT(列名)
илиCOUNT(常量)
заменитьCOUNT(*)
Шерстяная ткань?
Разница между COUNT (имя столбца), COUNT (константа) и COUNT (*)
Мы упоминали ранееCOUNT(expr)
Для статистики подсчета строк подсчетом является количество строк, в которых expr не равно NULL, тогдаCOUNT(列名)
,COUNT(常量)
иCOUNT(*)
В этих трех грамматиках expr列名
,常量
и*
.
Так列名
,常量
и*
Из этих трех условий常量
является фиксированным значением, определенно не NULL.*
Это можно понимать как запрос всей строки, поэтому она не должна быть NULL, тогда только列名
Результат запроса может быть NULL.
так,COUNT(常量)
иCOUNT(*)
Указывает количество строк в таблице базы данных, соответствующих критериям прямого запроса. иCOUNT(列名)
Указывает количество строк, для которых значение столбца, соответствующего запросу, не равно NULL.
Помимо разницы в результирующем наборе, полученном из запроса,COUNT(*)
по сравнению сCOUNT(常量)
иCOUNT(列名)
Говорящий,COUNT(*) — это стандартный синтаксис для подсчета строк, определенный в SQL 92. Поскольку это стандартный синтаксис, база данных MySQL выполнила для него много оптимизаций.
SQL92 — это стандарт ANSI/ISO для баз данных. Он определяет язык (SQL) и поведение базы данных (транзакции, уровни изоляции и т. д.).
Оптимизация COUNT(*)
упомянутый ранееCOUNT(*)
Это стандартный синтаксис для подсчета строк, определенный в SQL92, поэтому база данных MySQL провела большую оптимизацию. Итак, что именно вы сделали?
Введение здесь состоит в том, чтобы различать разные механизмы выполнения. Чаще всего в MySQL используются InnoDB и MyISAM.
Существует много различий между MyISAM и InnoDB, и есть одно ключевое отличие, которое мы рассмотрим далее.COUNT(*)
связанные, то естьMyISAM не поддерживает транзакции, а блокировки в MyISAM являются блокировками на уровне таблицы, в то время как InnoDB поддерживает транзакции и блокировки на уровне строк.
Поскольку блокировки MyISAM являются блокировками на уровне таблицы, операции над одной и той же таблицей должны выполняться последовательно, поэтомуMyISAM сделал простую оптимизацию, то есть он может записывать общее количество строк в таблице отдельно. Если вы используете COUNT(*) для запроса из таблицы, вы можете напрямую вернуть записанное значение. Конечно, предпосылка Не может быть условия where.
Причина, по которой MyISAM может записывать общее количество строк в таблице для запроса COUNT(*), заключается в том, что база данных MyISAM является блокировкой на уровне таблицы, и не будет одновременного изменения номера строки базы данных, поэтому количество строк, полученных с помощью запрос точен.
Однако для InnoDB такого рода операции с кэшем не могут быть выполнены, потому что InnoDB поддерживает транзакции, большинство из которых являются блокировками на уровне строк, поэтому количество строк в таблице может изменяться одновременно, поэтому общее количество строк, записанных в кеш не точный.
Однако InnoDB по-прежнему оптимизирован для инструкции COUNT(*).
В InnoDB при использовании COUNT(*) для запроса количества строк сканирование таблицы неизбежно, и тогда вы можете усердно работать над оптимизацией эффективности процесса сканирования таблицы.
Начиная с MySQL 8.0.13, для InnoDBSELECT COUNT(*) FROM tbl_name
Оператор сделал некоторые оптимизации в процессе сканирования таблицы. Предпосылка заключается в том, что оператор запроса не содержит таких условий, как WHERE или GROUP BY.
Мы знаем, что функция COUNT(*) предназначена только для подсчета общего количества строк, поэтому его вообще не волнуют конкретные значения, которые он находит, поэтому, если он может выбрать более низкий индекс стоимости в процессе сканирование таблицы, что может сэкономить много времени.
Мы знаем, что индексы в InnoDB делятся на кластеризованные индексы (индексы первичного ключа) и некластеризованные индексы (индексы непервичного ключа) — это значение первичного ключа записи строки.
Таким образом, некластеризованный индекс, напротив, намного меньше кластеризованного индекса, поэтомуMySQL предпочтет наименьший некластеризованный индекс для сканирования таблицы. Поэтому, когда мы строим таблицу, в дополнение к индексу первичного ключа необходимо создать индекс непервичного ключа.
До сих пор мы вводили оптимизацию COUNT(*) в базе данных MySQL.Предпосылкой этих оптимизаций является то, что оператор запроса не содержит условий WHERE и GROUP BY.
СЧЁТ(*) и СЧЁТ(1)
Введение оконченоCOUNT(*)
, см. далееCOUNT(1)
, В Интернете есть разные мнения о том, есть ли между ними разница.
некоторые говорятCOUNT(*)
будет преобразован вCOUNT(1)
, поэтому COUNT(1) имеет меньше шагов преобразования и, следовательно, быстрее.
Другие говорят, что поскольку MySQL нацелен наCOUNT(*)
Была проведена специальная оптимизация, поэтомуCOUNT(*)
Быстрее.
Итак, какое утверждение верно? Посмотрите, что говорится в официальной документации MySQL:
InnoDB handles SELECT COUNT(*) and SELECT COUNT(1) operations in the same way. There is no performance difference.
Фокус рисования:same way
, no performance difference
.Таким образом, для COUNT(1) и COUNT(*) оптимизация MySQL абсолютно одинакова, нет одного быстрее другого!
С того времениCOUNT(*)
иCOUNT(1)
Кроме того, какой из них вы рекомендуете?
Рекомендуется использоватьCOUNT(*)
! Поскольку это стандартный синтаксис для подсчета строк, определенный в SQL92, а эта статья основана только на MySQL для анализа, в Oracle существуют разные мнения по этому вопросу.
СЧЕТ(поле)
Наконец, это COUNT (поле), о котором мы еще не упоминали, его запрос относительно прост и груб, то есть выполняется полное сканирование таблицы, а затем определяется, является ли значение указанного поля равным NULL, и если это не NULL, оно накапливается.
по сравнению сCOUNT(*)
,COUNT(字段)
Еще один шаг — определить, является ли запрошенное поле NULL, поэтому его производительность лучше, чемCOUNT(*)
медленный.
Суммировать
В этой статье рассказывается об использовании функции COUNT, которая в основном используется для подсчета количества строк таблицы. Основные виды использованияCOUNT(*)
,COUNT(字段)
иCOUNT(1)
.
так какCOUNT(*)
Это стандартный синтаксис для подсчета количества строк, определенный SQL92, поэтому MySQL значительно оптимизировал его.MyISAM будет непосредственно записывать общее количество строк в таблице отдельно дляCOUNT(*)
запрос, и InnoDB выберет наименьший индекс при сканировании таблицы, чтобы сократить затраты. Конечно, предпосылкой этих оптимизаций является отсутствие условного запроса where и group.
в InnoDBCOUNT(*)
иCOUNT(1)
Разницы в реализации нет, а эффективность одинакова, ноCOUNT(字段)
Требуется оценка поля, отличная от NULL, поэтому эффективность будет ниже.
так какCOUNT(*)
Это стандартный синтаксис для подсчета строк, определенный в SQL92, и он эффективен, поэтому используйте его напрямую.COUNT(*)
Запрос количества строк в таблице!
Использованная литература:Dev.MySQL.com/doc/Furious/…«Geek Time — MySQL, практика, 45 лекций»