LINUX.ORG.RU

[MySQL] COUNT(*) WHERE

 


0

0

На хабре вы можете узнать, что для подсчета кол-ва строк (COUNT) MySQL обходит таблицу по индексам. Для меня это было шоком. Как? Зачем?? Т.е.

SELECT COUNT(*) FROM table WHERE key = 'some';

обойдет все записи по индексу и подсчитает их. А вот если выбрать чего из ключа:

SELECT key_part2 FROM table WHERE key_part1 = 'some' LIMIT 1;

то ни единой строчки не будет тронуто.

Вопросы:

  • Зачем дергать данные в COUNT? Зачем это нужно? Неужели нельзя подсчитать количество из индекса?
  • Есть ли какие способы это обойти? Окромя предложенного explain?
  • Откуда explain берет данные? Насколько им можно доверять?

на хабре мы вобще можем узнать много интересных и неверных вещей. Чтение документации к MySQL в данном случае могло бы раскрыть много интересного, что подсчёт count() зависит от движка таблицы, про count(*) и count(id) и вобще много интересных вещей :)

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

> на хабре мы вобще можем узнать много интересных и неверных вещей.

Я перепроверил. И по скорости это видно.

Чтение документации к MySQL в данном случае могло бы раскрыть много интересного, что подсчёт count() зависит от движка таблицы, про count(*) и count(id) и вобще много интересных вещей :)

От движка зависит, скорее всего, COUNT(*) без WHERE. Я совсем про другое.

Pavel_7c0
() автор топика

тогда ответ на вопрос №1:

For transactional storage engines such as InnoDB, storing an exact row count is more problematic because multiple transactions may be occurring, each of which may affect the count.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

> тогда ответ на вопрос №1:

Ещё раз. Вы мне говорите про «COUNT(*) is optimized to return very quickly if the SELECT retrieves from one table, no other columns are retrieved, and there is no WHERE clause». Я же спрашиваю про Count(*) WHERE, к тому же таблицы MyISAM. По сути, я хочу получение количества строк из индекса.

Pavel_7c0
() автор топика
Ответ на: комментарий от Pavel_7c0

Ещё раз. Вы мне говорите про «COUNT(*) is optimized to return very quickly if the SELECT retrieves from one table, no other columns are retrieved, and there is no WHERE clause». Я же спрашиваю про Count(*) WHERE, к тому же таблицы MyISAM. По сути, я хочу получение количества строк из индекса.

Вообще то в примере на хабре таблица InnoDB.

bibi
()

> # Откуда explain берет данные? Насколько им можно доверять?

Зависит от используемого storage engine. в MyISAM - лезет в индекс до каждой из границ диапазона, смотрит какая доля остается «слева» и «cправа», умножает долю на общее число записей и получает примерный результат.

В InnoDB посложнее но в целом похожий процесс.

MyISAM может промахиваться процентов на 20-30, InnoDB - до 2х раз. Точность очень зависит от того, сколько значений ключа помещается в B-дерево. Во всяких крайних случаях, или когда вертишься вокруг максимальных значений в индексе - может крупно промахиваться.

gods-little-toy ★★★
()
Ответ на: комментарий от Pavel_7c0

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

qnikst ★★★★★
()
Ответ на: комментарий от Pavel_7c0

> Я же спрашиваю про Count(*) WHERE, к тому же таблицы MyISAM. По сути, я хочу получение количества строк из индекса.

Оно и будет бегать только по индексу:

mysql> explain select count(*) from test2 where key1=1;
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+---------------+------+---------+-------+------+-------------+ 
| 1 | SIMPLE | test2 | ref | key1 | key1 | 5 | const | 2 | Using index | 
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+

А то, что одним махом число не возьмет - ну нету у MySQL-ных индексов такой возможности. в оракле вроде что-то такое есть, а тут нет.

gods-little-toy ★★★
()
Ответ на: комментарий от gods-little-toy

> MyISAM может промахиваться процентов на 20-30, InnoDB - до 2х раз.

Вот это уже интересно! Можно тогда такой алгоритм подсчета сделать: посмотреть что говорит EXPLAIN. Если число выше какого-то порога (страниц десять прокрутки), то округлить вниз и вывести, если ниже - уточнить.

А откуда информация, если не секрет?

Pavel_7c0
() автор топика
Ответ на: комментарий от gods-little-toy

Оно и будет бегать только по индексу:

Handler_read_next говорит об обратном. Скорость выполнения тоже.

А то, что одним махом число не возьмет - ну нету у MySQL-ных индексов такой возможности. в оракле вроде что-то такое есть, а тут нет.

Данные же из индекса вытягивать можно? Подсчитать ещё проще должно быть.

Черт. Сраный вонючий быдлохабр!

| Handler_read_next          | 441578 | 
| Handler_read_prev          | 0      | 
| Handler_read_rnd           | 0      | 
| Handler_read_rnd_next      | 0      | 

Handler_read_next — количество запросов на чтение следующей строки в порядке расположения ключей. Это значение будет увеличиваться, если производится запрос индексного столбца с ограничением по размеру. Значение также увеличивается во время проведения индексного сканирования.

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

Если в COUNT подставить левый столбец, то время возрастет на порядок и Handler_read_rnd_next покажет FULLSCAN.

Но я все равно не доволен ситуацией...

Pavel_7c0
() автор топика
Ответ на: комментарий от Pavel_7c0

> Черт. Сраный вонючий быдлохабр!

Хотя нет, это я не совсем внимательно прочитал статью. Но было бы лучше, если б прямо писали, что пробег осуществляется только про ключу.

Pavel_7c0
() автор топика
Ответ на: комментарий от true_admin

> не правда, это ты про show table status говоришь

Что я про show table status говорю? вот это?

Зависит от используемого storage engine. в MyISAM - лезет в индекс до каждой из границ диапазона, смотрит какая доля остается «слева» и «cправа», умножает долю на общее число записей и получает примерный результат.

и что такое «доля слева» и «доля справа»? я как раз говорю про числа которые получаются в EXPLAIN'e для range или ref с константой.

gods-little-toy ★★★
()
Ответ на: комментарий от gods-little-toy

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

При FULLTEXT (MATCH) всегда показывает 1. Жаль.

Pavel_7c0
() автор топика
Ответ на: комментарий от gods-little-toy

> я как раз говорю про числа которые получаются в EXPLAIN'e для range или ref с константой.

И все же, где об этом можно почитать?

P.S. При поиске по FULLTEXT показывает type=fulltext.

Pavel_7c0
() автор топика
Ответ на: комментарий от Pavel_7c0

> И все же, где об этом можно почитать?

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

P.S. При поиске по FULLTEXT показывает type=fulltext.

для fulltext вроде вообще оценок нету.

gods-little-toy ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.