MariaDB: несколько SELECT COUNT(*)

pastuhoff

Постоялец
Регистрация
11 Июл 2012
Сообщения
59
Реакции
8
Коллеги, подскажите, можно ли на такой таблице

CREATE TABLE `z` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`x` smallint(5) unsigned NOT NULL DEFAULT '0',
`a` int(11) unsigned NOT NULL DEFAULT '0',
`b` int(11) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `x` (`x`)
) ENGINE=Aria DEFAULT CHARSET=cp1251 PAGE_CHECKSUM=1 TRANSACTIONAL=0

объединить запросы

SELECT COUNT(*) AS n1 FROM `z` WHERE x=1
SELECT COUNT(*) AS n2 FROM `z` WHERE a=0 AND x=1
SELECT COUNT(*) AS n3 FROM `z` WHERE a=1 AND x=1
SELECT COUNT(*) AS n4 FROM `z` WHERE a>1 AND x=1
SELECT COUNT(*) AS n5 FROM `z` WHERE b=0 AND x=1
SELECT COUNT(*) AS n6 FROM `z` WHERE b=1 AND x=1
SELECT COUNT(*) AS n7 FROM `z` WHERE b>1 AND x=1

в один, дабы уменьшить общее время выполнения всех этих селектов (новые индексы создавать нельзя).
 
Подсказали следующее решение:

SELECT
SUM(1) AS `n1`,
SUM(IF(a=0,1,0)) AS `n2`,
SUM(IF(a=1,1,0)) AS `n3`,
SUM(IF(a>1,1,0)) AS `n4`,
SUM(IF(b=0,1,0)) AS `n5`,
SUM(IF(b=1,1,0)) AS `n6`,
SUM(IF(b>1,1,0)) AS `n7`
FROM `z` WHERE x=1

Это ведь уже нельзя ускорить?
 
а нельзя ли сделать отдельную колонку где будут значения
1 - WHERE x=1
2 - WHERE a=0 AND x=1
3 - WHERE a=1 AND x=1
4 - WHERE a>1 AND x=1
5 - WHERE b=0 AND x=1
6 - WHERE b=1 AND x=1
7 - WHERE b>1 AND x=1
а потом выборка по этому полю, + индексирования
апдейт поля при инсерте и апдейте таблички либо как значание передавать, либо триггер прицепить (есть в мускуле триггеры), либо кроном пересчитывать
 
Благодарю. Ваш вариант непозволительно увеличит размер файлов базы и замедлит изменения параметров a и b (в реальности там еще аналогичные c,d,...).
Приведенный вариант во втором посте в принципе устраивает. Разве что его можно как-то ускорить (не трогая триггеры, индексы, тип таблицы), изменив сам запрос на выборку на еще более хитроумный.
 
насколько непозволительно? в этом поле будет храниться минимум информации, тип поля вообще TINYINT скажем, это аж 1 байт :crazy:, сколько же записей в таблице у вас, чтоб этот 1 байт привёл к существенному увеличению? :smmne:

а вообще, попробуйте оба варианта, желательно на 10К-1М записях и посмотрите внимательно план выполнения запроса :-]
ну и последнее, даже если у вас там есть ещё c, d, e ... колонки, которые, кстате, нигде не видны в примере, подход с поле, где указано группу по которой суммировать опять же работает
 
Последнее редактирование:
Мне критично важно очень частое (~100% времени процессор загружен именно этим на ~100%) изменение полей a,b и т.д. Это нужно делать максимально быстро. Записей пока 600+ миллионов.
 
А в чем проблема использовать UNION?
Код:
SELECT COUNT(*) AS n1 FROM `z` WHERE x=1
UNION
SELECT COUNT(*) AS n1 FROM `z` WHERE a=0 AND x=1
только везде использовать "AS n1" а в программе выбирать значения по номеру строки результата
 
А в чем проблема использовать UNION?
Код:
SELECT COUNT(*) AS n1 FROM `z` WHERE x=1
UNION
SELECT COUNT(*) AS n1 FROM `z` WHERE a=0 AND x=1
только везде использовать "AS n1" а в программе выбирать значения по номеру строки результата

Как я понял, такой вариант сделает столько-же проходов по данным, как отдельные запросы, указанные в первом посте.
 
Подсказали следующее решение:



Это ведь уже нельзя ускорить?

Нет, это уже хорошо. На пустой таблице нужно IFNULL везде будет постаивть типа

SELECT
IFNULL(SUM(1),0) AS `n1`,
SUM(IF(a=0,1,0)) AS `n2`,
SUM(IF(a=1,1,0)) AS `n3`,
SUM(IF(a>1,1,0)) AS `n4`,
SUM(IF(b=0,1,0)) AS `n5`,
SUM(IF(b=1,1,0)) AS `n6`,
SUM(IF(b>1,1,0)) AS `n7`
FROM `z` WHERE x=1
 
Не совсем понял, зачем "IFNULL", если все поля "NOT NULL". Вот IF`ы как-то на CASE заменить не нужно? Не получится сделать быстрее?
 
Назад
Сверху