подсчитать кол-во уникальных значений без селекта
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.04.18 13:29
Оценка:
привет!

есть такая MySql БД:
int game_id
int distr_id

нужно подсчитать кол-во уникальных distr_id в запросе:
SELECT COUNT(DISTINCT distr_id) FROM mytable where game_id=33 AND distr_id>=44 ORDER BY distr_id;

этот запрос работает как надо за одним исключением — долго.
долго, я думаю, потому, — происходит реальный селект всех distr_id, и потом к ним применяется DISTINCT и только потом — COUNT().
индексы для game_id и distr_id созданы.

вопрос в том, как ускорить?

спасибо.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Отредактировано 06.04.2018 13:30 niXman . Предыдущая версия . Еще …
Отредактировано 06.04.2018 13:29 niXman . Предыдущая версия .
Re: подсчитать кол-во уникальных значений без селекта
От: kov_serg Россия  
Дата: 06.04.18 13:45
Оценка: +3
Здравствуйте, niXman, Вы писали:

X>вопрос в том, как ускорить?

index (game_id,dist_id) ?
Re: подсчитать кол-во уникальных значений без селекта
От: Maniacal Россия  
Дата: 06.04.18 13:47
Оценка: +3
Здравствуйте, niXman, Вы писали:

X>
X>SELECT COUNT(DISTINCT distr_id) FROM mytable where game_id=33 AND distr_id>=44 ORDER BY distr_id;
X>


ORDER BY distr_id

Это ещё зачем?
Re: подсчитать кол-во уникальных значений без селекта
От: torvic Голландия  
Дата: 06.04.18 13:50
Оценка: +1
Здравствуйте, niXman, Вы писали:
X>долго, я думаю, потому...
а планов нет в mysql?
Re: подсчитать кол-во уникальных значений без селекта
От: Sharov Россия  
Дата: 06.04.18 13:50
Оценка: +1
Здравствуйте, niXman, Вы писали:

X>SELECT COUNT(DISTINCT distr_id) FROM mytable where game_id=33 AND distr_id>=44 ORDER BY distr_id;



Выше уже отметили -- если COUNT, то зачем ORDER BY?
Кодом людям нужно помогать!
Re[2]: подсчитать кол-во уникальных значений без селекта
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.04.18 13:54
Оценка:
Здравствуйте, Maniacal, Вы писали:

M>

M>ORDER BY distr_id

M>Это ещё зачем?

да, лишнее.
убрал — ничего по времени не изменилось...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: подсчитать кол-во уникальных значений без селекта
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.04.18 13:55
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>index (game_id,dist_id) ?


думаете, есть смысл пробовать?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: подсчитать кол-во уникальных значений без селекта
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.04.18 13:55
Оценка:
Здравствуйте, torvic, Вы писали:

T>а планов нет в mysql?

а это что? =)
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: подсчитать кол-во уникальных значений без селекта
От: torvic Голландия  
Дата: 06.04.18 14:07
Оценка:
Здравствуйте, niXman, Вы писали:

X>Здравствуйте, torvic, Вы писали:


T>>а планов нет в mysql?

X>а это что? =)
query execution plan
погуглил:
https://dev.mysql.com/doc/refman/5.5/en/execution-plan-information.html
Re: подсчитать кол-во уникальных значений без селекта
От: Maniacal Россия  
Дата: 06.04.18 14:22
Оценка:
Здравствуйте, niXman, Вы писали:

X>вопрос в том, как ускорить?


Некоторые люди пишут, что иногда лучше использовать GROUP BY.
Под рукой нет MySQL, может, стоит попробовать что-нибудь эдакое:
SELECT count(distr_id) FROM (SELECT distr_id FROM mytable where game_id=33 AND distr_id>=44) GROUP BY distr_id


И да. Команда EXPLAIN перед запросом покажет план выполнения и узкие места (FULL SCAN).
Re[2]: подсчитать кол-во уникальных значений без селекта
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.04.18 14:41
Оценка:
Здравствуйте, Maniacal, Вы писали:

M>Некоторые люди пишут, что иногда лучше использовать GROUP BY.

M>Под рукой нет MySQL, может, стоит попробовать что-нибудь эдакое:
M>
M>SELECT count(distr_id) FROM (SELECT distr_id FROM mytable where game_id=33 AND distr_id>=44) GROUP BY distr_id
M>


вот попытался, но получаю такую ошибку: every derived table must have its own alias
я тот еще спец по БД, и не очень понимаю, что нужно поправить в вашем примере...

M>И да. Команда EXPLAIN перед запросом покажет план выполнения и узкие места (FULL SCAN).

ща попробую...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: подсчитать кол-во уникальных значений без селекта
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.04.18 14:47
Оценка: :)
Здравствуйте, niXman, Вы писали:

X>вот попытался, но получаю такую ошибку: every derived table must have its own alias


поправил. но этот способ еще дольше выполняется...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[4]: подсчитать кол-во уникальных значений без селекта
От: niXman Ниоткуда https://github.com/niXman
Дата: 06.04.18 14:56
Оценка:
ну и как костыль — могу добавить таблицу, в которой тригером апдейтить кол-во действий для конкретной игры...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: подсчитать кол-во уникальных значений без селекта
От: Milena США  
Дата: 08.04.18 14:57
Оценка:
Здравствуйте, niXman, Вы писали:

X>привет!


X>есть такая MySql БД:

X>
X>int game_id
X>int distr_id
X>

X>нужно подсчитать кол-во уникальных distr_id в запросе:
X>
X>SELECT COUNT(DISTINCT distr_id) FROM mytable where game_id=33 AND distr_id>=44 ORDER BY distr_id;
X>


X>вопрос в том, как ускорить?


Я не знаю, какой у вас PK на этой таблице. В идеале для долго работающих запросов нужен покрывающий индекс, чтобы запрос не обращался к PK вообще и брал всю инфу из индекса.
Можно попробовать ещё так — добавить позапрос, что сократить возврат количества данных, по которому работает distinct:

SELECT COUNT(DISTINCT t1.distr_id)
FROM
(  SELECT distr_id 
   FROM mytable 
   WHERE game_id=33) AS t1
WHERE t1.distr_id>=44;


И ещё рекомендую проверить фрагментацию ваших индексов.
Re[5]: подсчитать кол-во уникальных значений без селекта
От: niXman Ниоткуда https://github.com/niXman
Дата: 10.04.18 07:48
Оценка:
Здравствуйте, niXman, Вы писали:

X>ну и как костыль — могу добавить таблицу, в которой тригером апдейтить кол-во действий для конкретной игры...

глупость написал
мне же нужно не просто знать кол-во действий для игры, но кол-во действий начиная с какого-то конкретного ID`а действия...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[2]: подсчитать кол-во уникальных значений без селекта
От: niXman Ниоткуда https://github.com/niXman
Дата: 10.04.18 07:52
Оценка:
Здравствуйте, Milena, Вы писали:

M>Я не знаю, какой у вас PK на этой таблице. В идеале для долго работающих запросов нужен покрывающий индекс, чтобы запрос не обращался к PK вообще и брал всю инфу из индекса.

РК — id, тут он вообще не используется...

M>Можно попробовать ещё так — добавить позапрос, что сократить возврат количества данных, по которому работает distinct:


M>
M>SELECT COUNT(DISTINCT t1.distr_id)
M>FROM
M>(  SELECT distr_id 
M>   FROM mytable 
M>   WHERE game_id=33) AS t1
M>WHERE t1.distr_id>=44;
M>


да, для distinct сократит, но при этом селектит все distr_id для конкретной игры, коих миллионы...
т.е. этот способ самый долгий...

M>И ещё рекомендую проверить фрагментацию ваших индексов.

это что?
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Отредактировано 10.04.2018 8:22 niXman . Предыдущая версия .
Re[3]: В России опять напишут новый объектно-ориентированны
От: Sinclair Россия https://github.com/evilguest/
Дата: 10.04.18 17:34
Оценка:
Здравствуйте, niXman, Вы писали:
X>думаете, есть смысл пробовать?
Зависит от количества различных game_id в таблице.
Если их, скажем, 2, то такой индекс всего лишь уполовинит время работы запроса.
А если их миллион — то и работать будет в миллион раз быстрее.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: подсчитать кол-во уникальных значений без селекта
От: Sergei MO Россия  
Дата: 13.04.18 08:04
Оценка: 12 (1) +1
Здравствуйте, niXman, Вы писали:

X>>ну и как костыль — могу добавить таблицу, в которой тригером апдейтить кол-во действий для конкретной игры...

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

Можно добавить вспомогательную таблицу следующей структуры:
SELECT game_id, distr_id DIV 1000 AS distr_range, COUNT(game_id) AS count FROM mytable GROUP BY game_id, distr_range;


Триггером поддерживать её согласованность с основной таблицей. Исходный запрос разбивается на две части — одна часть работает по неполному диапазону distr_id из исходной таблицы, а вторая — суммирует все полные диапазоны из вспомогательной. Таким образом вместо одного запроса на миллионы записей будет два запроса на тысячи.
Re[7]: подсчитать кол-во уникальных значений без селекта
От: niXman Ниоткуда https://github.com/niXman
Дата: 13.04.18 08:09
Оценка:
Здравствуйте, Sergei MO, Вы писали:

SM>Можно добавить вспомогательную таблицу следующей структуры:

SM>
SM>SELECT game_id, distr_id DIV 1000 AS distr_range, COUNT(game_id) AS count FROM mytable GROUP BY game_id, distr_range;
SM>


SM>Триггером поддерживать её согласованность с основной таблицей. Исходный запрос разбивается на две части — одна часть работает по неполному диапазону distr_id из исходной таблицы, а вторая — суммирует все полные диапазоны из вспомогательной. Таким образом вместо одного запроса на миллионы записей будет два запроса на тысячи.


это просто великолепно!
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[8]: подсчитать кол-во уникальных значений без селекта
От: Sergei MO Россия  
Дата: 13.04.18 08:36
Оценка:
Здравствуйте, niXman, Вы писали:

Только я забыл про неуникальность значений пары (game_id, distr_id). Чтобы решение работало, нужно каким-то образом от неё избавиться.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.