Я должен РАССЧИТАТЬ (*) или нет?

это для Мальчика:

select party_code 
from abc as a
where party_code not in (select party_code 
                         from xyz 
                         where party_code = a.party_code);

работает независимо от настроек ansi

72
задан grapefrukt 19 January 2009 в 12:57
поделиться

14 ответов

Если рассматриваемый столбец является NOT NULL, оба из Ваших запросов эквивалентны. Когда group_id содержит нулевые значения,

select count(*)

будет считать все строки, тогда как

select count(group_id)

будет только считать строки, где group_id не является пустым.

кроме того, некоторые системы баз данных, как MySQL используют оптимизацию, когда Вы просите количество (*), который делает такие запросы немного быстрее, чем определенный.

Лично, просто рассчитывая, я провожу подсчет (*), чтобы быть на безопасной стороне с пустыми указателями.

101
ответ дан Iain Holder 7 November 2019 в 08:24
поделиться

Это должно зависеть от того, чего Вы на самом деле пытаетесь достигнуть, как Sebastian уже сказал, т.е. ясно дает понять Ваши намерения! Если Вы , просто подсчет строк тогда идет для КОЛИЧЕСТВА (*), или подсчет отдельного столбца идет для КОЛИЧЕСТВА (столбец).

могло бы стоить проверить Вашего поставщика DB также. Назад, когда я раньше использовал Informix, он имел оптимизацию для КОЛИЧЕСТВА (*), который имел стоимость осуществления плана запросов 1 по сравнению с подсчетом единственного или несколько столбцов, которые приведут к более высокому рисунку

1
ответ дан tddmonkey 7 November 2019 в 08:24
поделиться

при попытке ИЗБРАННОГО КОЛИЧЕСТВА (1) ОТ group_relations это будет немного быстрее, потому что это не попытается получить информацию из столбцов.

КОЛИЧЕСТВО (1) раньше было быстрее, чем КОЛИЧЕСТВО (*), но это больше не верно, начиная с современного DBMS достаточно умны, чтобы знать, что Вы не хотите знать о столбцах

1
ответ дан Rafael Mueller 7 November 2019 в 08:24
поделиться

Звездочка в КОЛИЧЕСТВЕ не имеет никакого терпения звездочки для выбора всех полей таблицы. Это - чистый мусор, чтобы сказать, что КОЛИЧЕСТВО (*) медленнее, чем КОЛИЧЕСТВО (поле)

, я постигаю интуитивно то избранное КОЛИЧЕСТВО (*), быстрее, чем избранное КОЛИЧЕСТВО (поле). Если RDBMS обнаружил, что Вы определяете "*" на КОЛИЧЕСТВЕ вместо поля, это не должно оценивать ничего для постепенного увеличения количества. Принимая во внимание, что при определении поля на КОЛИЧЕСТВЕ RDBMS будет всегда оценивать, если поле будет пустым или не считать его.

, Но если Ваше поле nullable, определите поле в КОЛИЧЕСТВЕ.

2
ответ дан Michael Buen 7 November 2019 в 08:24
поделиться

КОЛИЧЕСТВО (*) факты и мифы:

МИФ : "InnoDB не обрабатывает количество (*) запросы хорошо":

Большая часть количества (*) запросы выполняются тот же путь всеми механизмами устройства хранения данных, если у Вас есть оператор Where, иначе Вы, InnoDB должен будет выполнить полное сканирование таблицы.

ФАКТ : InnoDB не оптимизирует количество (*) запросы без где пункт

2
ответ дан Charles Faiga 7 November 2019 в 08:24
поделиться

Если я помню, что это правильный, в КОЛИЧЕСТВЕ MySQL (*) считает все строки, тогда как КОЛИЧЕСТВО (column_name) считает только строки, которые имеют ненулевое значение в данном столбце.

22
ответ дан Sebastian Dietz 7 November 2019 в 08:24
поделиться

Мне было любопытно на предмет этого самому. Это - весь штраф для чтения документации и теоретических ответов, но мне нравится балансировать тех, которые имеют эмпирическое доказательство.

у меня есть таблица MySQL (InnoDB), который имеет 5 607 997 записей в ней. Таблица находится в моей собственной частной песочнице, таким образом, я знаю, что содержание статично, и никто больше не использует сервер. Я думаю, что это эффективно удаляет все внешнее влияние на производительности. У меня есть таблица с auto_increment полем Primary Key (идентификатор), который я, никогда знаю не будет пустым, который я буду использовать для моего, где тест пункта (ГДЕ идентификатор ЯВЛЯЕТСЯ NOT NULL).

Единственный другой возможный незначительный сбой я вижу в запущении тестов, кэш. В первый раз запрос выполняется, всегда будет медленнее, чем последующие запросы, которые используют те же индексы. Я обращусь к этому ниже как вызов Отбора кэша. Только для спутывания его немного я выполнил его с, где пункт, который я знаю, будет всегда оценивать к истинному независимо от любых данных (TRUE = TRUE).

, Который сказал вот, мои результаты:

КОЛИЧЕСТВО QueryType

      |  w/o WHERE          | where id is not null |  where true=true

()

      |  9 min 30.13 sec ++ | 6 min 16.68 sec ++   | 2 min 21.80 sec ++
      |  6 min 13.34 sec    | 1 min 36.02 sec      | 2 min 0.11 sec 
      |  6 min 10.06 se     | 1 min 33.47 sec      | 1 min 50.54 sec

КОЛИЧЕСТВО (идентификатор)

      |  5 min 59.87 sec    | 1 min 34.47 sec      | 2 min 3.96 sec 
      |  5 min 44.95 sec    | 1 min 13.09 sec      | 2 min 6.48 sec

КОЛИЧЕСТВО (1)

      | 6 min 49.64 sec    | 2 min 0.80 sec       | 2 min 11.64 sec
      | 6 min 31.64 sec    | 1 min 41.19 sec      | 1 min 43.51 sec

++ Это считают вызовом Отбора кэша. Это, как ожидают, будет медленнее, чем остальные.

я сказал бы, что результаты выступают за себя. КОЛИЧЕСТВО (Айдахо) обычно вычеркивает другие. Добавление оператора Where существенно уменьшает время доступа, даже если это будет пункт, который Вы знаете, то оценит к истинному. Зона наилучшего восприятия, кажется, КОЛИЧЕСТВО (идентификатор)... ГДЕ идентификатор ЯВЛЯЕТСЯ NOT NULL.

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

5
ответ дан Chris 7 November 2019 в 08:24
поделиться

если Вы попробуете SELECT COUNT(1) FROM group_relations, то это будет немного быстрее, потому что это не попытается получить информацию из Ваших столбцов.

Редактирование: Я просто провел некоторое исследование и узнал, что это только происходит в некотором дб. В sqlserver это - то же для использования 1 или *, но на оракуле это быстрее для использования 1.

http://social.msdn.microsoft.com/forums/en-US/transactsql/thread/9367c580-087a-4fc1-bf88-91a51a4ee018/

, По-видимому, нет никакого различия между ними в mysql, как sqlserver, который синтаксический анализатор, кажется, изменяет запрос для выбора (1). Извините, если я ввожу в заблуждение Вас в некотором роде.

8
ответ дан Sergio 7 November 2019 в 08:24
поделиться

КОЛИЧЕСТВО (*) считает все строки, в то время как КОЛИЧЕСТВО (column_name) будет считать только строки без Нулевых значений в указанном столбце.

Важный для замечания в MySQL:

КОЛИЧЕСТВО () очень быстро на таблицах MyISAM для * или не - пустые столбцы, так как количество строки кэшируется. InnoDB не имеет никакого кэширования количества строки, таким образом, нет никакой разницы в производительности для КОЛИЧЕСТВА (*) или КОЛИЧЕСТВА (column_name), независимо если столбец может быть пустым или нет. Можно читать больше на различиях на это сообщение в блоге производительности MySQL.

11
ответ дан Eran Galperin 7 November 2019 в 08:24
поделиться

Таблицы MySQL ISAM должны иметь оптимизацию для КОЛИЧЕСТВА (*), пропуская полное сканирование таблицы.

2
ответ дан dmajkic 7 November 2019 в 08:24
поделиться

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

Запишите запрос, который отвечает на вопрос, который Вы задаете - если Вы хотите количество всех строк, используйте КОЛИЧЕСТВО (*). Если Вы хотите количество непустых столбцов, используйте КОЛИЧЕСТВО (седло), ГДЕ седлом ЯВЛЯЕТСЯ NOT NULL. Индексируйте соответственно и оставьте оптимизацию оптимизатору. Попытка сделать Вашу собственную оптимизацию уровня запроса может иногда делать встроенный оптимизатор менее эффективным.

Тем не менее существуют вещи, которые можно сделать в запросе, чтобы помочь оптимизатору ускорить его, но я не полагаю, что КОЛИЧЕСТВО является одним из них.

Править: Статистические данные в ответе выше интересны, все же. Я не уверен, существует ли на самом деле что-то на работе в оптимизаторе в этом случае. Я просто говорю об оптимизации уровня запроса в целом.

1
ответ дан Jon 24 November 2019 в 12:36
поделиться

Я знаю, что это вообще плохая идея запросы типа этого:

 SELECT * FROM `group_relations`

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

 SELECT COUNT (*) FROM `group_relations`

Как следует из вашего вопроса, причина SELECT * не рекомендуется в том, что изменения в таблице могут потребовать изменений в вашем коде. Это не относится к COUNT (*) . Довольно редко требуется специализированное поведение, которое дает SELECT COUNT ('group_id') - обычно вы хотите знать количество записей. Для этого предназначен COUNT (*) , поэтому используйте его.

0
ответ дан 24 November 2019 в 12:36
поделиться

Лучше всего производить подсчет по индексированному столбцу, например по первичному ключу.

SELECT COUNT(`group_id`) FROM `group_relations`
2
ответ дан 24 November 2019 в 12:36
поделиться

Искать альтернативы

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

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

Denormalize

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

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

BEGIN TRANSACTION;
INSERT INTO  `group_relations` (`group_id`) VALUES (1);
UPDATE `group_relations_count` SET `count` = `count` + 1;
COMMIT;

В качестве альтернативы вы можете использовать триггеры базы данных, если ваша СУБД поддерживает их.

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

и уменьшая этот счетчик при удалении записи.

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

BEGIN TRANSACTION;
INSERT INTO  `group_relations` (`group_id`) VALUES (1);
UPDATE `group_relations_count` SET `count` = `count` + 1;
COMMIT;

В качестве альтернативы вы можете использовать триггеры базы данных, если ваша СУБД поддерживает их.

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

и уменьшая этот счетчик при удалении записи.

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

BEGIN TRANSACTION;
INSERT INTO  `group_relations` (`group_id`) VALUES (1);
UPDATE `group_relations_count` SET `count` = `count` + 1;
COMMIT;

В качестве альтернативы вы можете использовать триггеры базы данных, если ваша СУБД поддерживает их.

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

BEGIN TRANSACTION;
INSERT INTO  `group_relations` (`group_id`) VALUES (1);
UPDATE `group_relations_count` SET `count` = `count` + 1;
COMMIT;

В качестве альтернативы вы можете использовать триггеры базы данных, если ваша СУБД поддерживает их.

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

BEGIN TRANSACTION;
INSERT INTO  `group_relations` (`group_id`) VALUES (1);
UPDATE `group_relations_count` SET `count` = `count` + 1;
COMMIT;

В качестве альтернативы вы можете использовать триггеры базы данных, если ваша СУБД поддерживает их.

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

4
ответ дан 24 November 2019 в 12:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: