2016-11-18 4 views
1

Ниже запрос, который занимает почти 7-х и Im запутаться, если его нормальное поведение в mysqlserver (NDB хранение двигателя), пояснения из положить это также показывает, что используется таблица индексовMySQL запрос застрял состояние «отправки данных»

SELECT radgroupreply.groupname, 
    count(distinct(radusergroup.username)) AS users 
    FROM radgroupreply     
    JOIN radusergroup ON radgroupreply.groupname=radusergroup.groupname         
    WHERE 
    (radgroupreply.groupname NOT LIKE 'FB-%' 
    AND radgroupreply.groupname <> 'Dropped Corporate Users' 
    AND radgroupreply.groupname <> 'Dropped Broadband Users') 
    GROUP BY radgroupreply.groupname 
    UNION 
    SELECT distinct(radgroupcheck.groupname), 
    count(distinct(radusergroup.username)) 
    FROM radgroupcheck 
    JOIN radusergroup ON radgroupcheck.groupname=radusergroup.groupname     
    WHERE 
    (radgroupcheck.groupname NOT LIKE 'FB-%' 
    AND radgroupcheck.groupname <> 'Dropped Corporate Users' 
    ) 
    GROUP BY radgroupcheck.groupname ORDER BY groupname asc; 

explain выхода для запроса: -

+----+--------------+---------------+-------+---------------+-----------+---------+----------------------------------+------+---------------------------------+ 
    | id | select_type | table   | type | possible_keys | key  | key_len | ref        | rows | Extra       | 
    +----+--------------+---------------+-------+---------------+-----------+---------+----------------------------------+------+---------------------------------+ 
    | 1 | PRIMARY  | radgroupreply | range | groupname  | groupname | 66  | NULL        | 47 | Using where; Using MRR   | 
    | 1 | PRIMARY  | radusergroup | ref | groupname  | groupname | 66  | ctradius.radgroupreply.groupname | 64 | NULL       | 
    | 2 | UNION  | radgroupcheck | range | groupname  | groupname | 66  | NULL        | 20 | Using where; Using MRR   | 
    | 2 | UNION  | radusergroup | ref | groupname  | groupname | 66  | ctradius.radgroupcheck.groupname | 120 | NULL       | 
    |NULL| UNION RESULT | <union1,2> | ALL | NULL   | NULL  | NULL | NULL        | NULL | Using temporary; Using filesort | 
    +----+--------------+---------------+-------+---------------+-----------+---------+----------------------------------+------+---------------------------------+ 

Ниже приводится структура таблицы и индексированная информация столбца для таблиц, участвующих в присоединиться

Таблица: radgroupreply; # всего 192 строк

+-----------+------------------+------+-----+---------+----------------+ 
    | Field  | Type    | Null | Key | Default | Extra   | 
    +-----------+------------------+------+-----+---------+----------------+ 
    | id  | int(11) unsigned | NO | PRI | NULL | auto_increment | 
    | groupname | varchar(64)  | NO | MUL |   |    | 
    | attribute | varchar(32)  | NO |  |   |    | 
    | op  | char(2)   | NO |  | =  |    | 
    | value  | varchar(253)  | NO |  |   |    | 
    +-----------+------------------+------+-----+---------+----------------+ 

Таблица: radusergroup #total: ~ 13000 строк

+-----------+-------------+------+-----+---------+----------------+ 
    | Field  | Type  | Null | Key | Default | Extra   | 
    +-----------+-------------+------+-----+---------+----------------+ 
    | id  | int(11)  | NO | PRI | NULL | auto_increment | 
    | username | varchar(64) | NO | MUL |   |    | 
    | groupname | varchar(64) | NO | MUL |   |    | 
    | priority | int(11)  | NO |  | 1  |    | 
    +-----------+-------------+------+-----+---------+----------------+ 

Таблица: radgroupcheck #totalrows: ~ 100

+-----------+------------------+------+-----+---------+----------------+ 
    | Field  | Type    | Null | Key | Default | Extra   | 
    +-----------+------------------+------+-----+---------+----------------+ 
    | id  | int(11) unsigned | NO | PRI | NULL | auto_increment | 
    | groupname | varchar(64)  | NO | MUL |   |    | 
    | attribute | varchar(32)  | NO |  |   |    | 
    | op  | char(2)   | NO |  | ==  |    | 
    | value  | varchar(253)  | NO |  |   |    | 
    +-----------+------------------+------+-----+---------+----------------+ 


    #radusergroup# CREATE TABLE `radusergroup` (
     `id` int(11) NOT NULL AUTO_INCREMENT, 
     `username` varchar(64) NOT NULL DEFAULT '', 
     `groupname` varchar(64) NOT NULL DEFAULT '', 
     `priority` int(11) NOT NULL DEFAULT '1', 
     PRIMARY KEY (`id`), 
     KEY `groupname` (`groupname`), 
     KEY `username` (`username`) 
    ) ENGINE=ndbcluster AUTO_INCREMENT=12380 DEFAULT CHARSET=latin1 

    #show index from radusergroup 
    +---------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
    | Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
    +---------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
    | radgroupreply |   0 | PRIMARY |   1 | id   | A   |   192 |  NULL | NULL |  | BTREE  |   |    | 
    | radgroupreply |   1 | groupname |   1 | groupname | A   |  NULL |  NULL | NULL |  | BTREE  |   |    | 
    +---------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 

    #radgroupreply# CREATE TABLE `radgroupreply` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `groupname` varchar(64) NOT NULL DEFAULT '', 
    `attribute` varchar(32) NOT NULL DEFAULT '', 
    `op` char(2) NOT NULL DEFAULT '=', 
    `value` varchar(253) NOT NULL DEFAULT '', 
    PRIMARY KEY (`id`), 
    KEY `groupname` (`groupname`) 
    ) ENGINE=ndbcluster AUTO_INCREMENT=2410 DEFAULT CHARSET=latin1 
    mysql> show index from radgroupreply; 

    +---------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
    | Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
    +---------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
    | radgroupreply |   0 | PRIMARY |   1 | id   | A   |   192 |  NULL | NULL |  | BTREE  |   |    | 
    | radgroupreply |   1 | groupname |   1 | groupname | A   |  NULL |  NULL | NULL |  | BTREE  |   |    | 
    +---------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 

    #radgroupcheck# CREATE TABLE `radgroupcheck` (
     `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
     `groupname` varchar(64) NOT NULL DEFAULT '', 
     `attribute` varchar(32) NOT NULL DEFAULT '', 
     `op` char(2) NOT NULL DEFAULT '==', 
     `value` varchar(253) NOT NULL DEFAULT '', 
     PRIMARY KEY (`id`), 
     KEY `groupname` (`groupname`) 
    ) ENGINE=ndbcluster AUTO_INCREMENT=588 DEFAULT CHARSET=latin1 

    mysql> show index from radgroupcheck; 
    +---------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
    | Table   | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | 
    +---------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 
    | radgroupcheck |   0 | PRIMARY |   1 | id   | A   |   103 |  NULL | NULL |  | BTREE  |   |    | 
    | radgroupcheck |   1 | groupname |   1 | groupname | A   |  NULL |  NULL | NULL |  | BTREE  |   |    | 
    +---------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ 


mysql> SELECT @@GLOBAL.tx_isolation, @@tx_isolation, @@session.tx_isolation; 
+-----------------------+----------------+------------------------+ 
| @@GLOBAL.tx_isolation | @@tx_isolation | @@session.tx_isolation | 
+-----------------------+----------------+------------------------+ 
| READ-COMMITTED  | READ-COMMITTED | READ-COMMITTED   | 
+-----------------------+----------------+------------------------+ 

обновление: Запрос

(SELECT radgroupreply.groupname, 
    count(distinct(radusergroup.username)) AS users 
    FROM radgroupreply     
    JOIN radusergroup ON radgroupreply.groupname=radusergroup.groupname         
    WHERE 
    (radgroupreply.groupname NOT LIKE 'FB-%' AND radgroupreply.groupname <> 'Dropped Corporate Users' AND radgroupreply.groupname <> 'Dropped Broadband Users') 
    GROUP BY radgroupreply.groupname) 
    UNION 
    (SELECT radgroupcheck.groupname, 
    count(distinct(radusergroup.username)) 
    FROM radgroupcheck 
    JOIN radusergroup ON radgroupcheck.groupname=radusergroup.groupname     
    WHERE 
    (radgroupcheck.groupname NOT LIKE 'FB-%' AND radgroupcheck.groupname <> 'Dropped Corporate Users') 
    GROUP BY radgroupcheck.groupname ORDER BY groupname asc); 

Объясните: -

+----+--------------+---------------+-------+---------------+-----------+---------+----------------------------------+------+------------------------+ 
    | id | select_type | table   | type | possible_keys | key  | key_len | ref        | rows | Extra     | 
    +----+--------------+---------------+-------+---------------+-----------+---------+----------------------------------+------+------------------------+ 
    | 1 | PRIMARY  | radgroupreply | range | groupname  | groupname | 66  | NULL        | 47 | Using where; Using MRR | 
    | 1 | PRIMARY  | radusergroup | ref | groupname  | groupname | 66  | ctradius.radgroupreply.groupname | 64 | NULL     | 
    | 2 | UNION  | radgroupcheck | range | groupname  | groupname | 66  | NULL        | 20 | Using where; Using MRR | 
    | 2 | UNION  | radusergroup | ref | groupname  | groupname | 66  | ctradius.radgroupcheck.groupname | 121 | NULL     | 
    |NULL| UNION RESULT | <union1,2> | ALL | NULL   | NULL  | NULL | NULL        | NULL | Using temporary  | 
    +----+--------------+---------------+-------+---------------+-----------+---------+----------------------------------+------+------------------------+ 
+0

Не уделяйте слишком много внимания фразе «отправка данных». Темы иногда сообщают, что находятся в этом состоянии, прежде чем они фактически «отправляют» что-либо. Есть ли причина использовать 'UNION' (который в современных версиях подразумевает« UNION DISTINCT »), а не явно« UNION ALL »? Во втором запросе 'SELECT distinct (radgroupcheck.groupname)' 'не должен быть' DISTINCT' - это группа, поэтому она обязательно различна - и ненужное использование 'DISTINCT' может быть настоящим убийцей производительности, и вы появляетесь делать это дважды. Что-то антипаттерна красный флаг в глаза DBA. –

+0

'DISTINCT (a, b)' - 'DISTINCT' не является функцией. –

+1

Зачем проверять «Корпоративный» дважды во второй части? –

ответ

2

Поскольку вы уже GROUPing BY, что изменение столбца SELECT distinct(radgroupcheck.groupname) в SELECT radgroupcheck.groupname

Добавить скобки уточнить, что UNION сортируется, а не только последний SELECT:

(SELECT ...) UNION (SELECT ...) ORDER BY ... 

Изменение много: много таблиц согласно подсказкам here (за исключением двигателя).

group_reply и group_check, похоже, имеют одинаковые схемы; по какой-то причине, чтобы они были отдельными?

Есть ли уникальная колонка (или пара столбцов) в group_reply и group_check, которые могут быть использованы для PRIMARY KEY?

Реконструкция

SELECT groupname, 
     (SELECT count(distinct username) 
      FROM radusergroup WHERE groupname = u.groupname 
     ) AS users 
    FROM ( 
      (
       SELECT r.groupname 
        FROM radgroupreply AS r 
        WHERE r.groupname NOT LIKE 'FB-%' 
         AND r.groupname <> 'Dropped Corporate Users' 
         AND r.groupname <> 'Dropped Broadband Users' 
      ) 
      UNION DISTINCT -- or UNION ALL ? 
      (
       SELECT c.groupname 
        FROM radgroupcheck AS c 
        WHERE c.groupname NOT LIKE 'FB-%' 
         AND c.groupname <> 'Dropped Corporate Users' 
      ) 
     ) AS u 
    ORDER BY groupname asc 
+0

Нет уникальных столбцов в groupreply и groupcheck, я не знаю, почему groupreply и groupcheck хранятся отдельно, поскольку эти таблицы уже существуют (унаследованная система связана с свободным радиусом). Я изменил запрос (обновленный в сообщении с объяснением вывода), но время выполнения почти идентично 4.4-5.5 секунд. Спасибо за ссылку, очень полезную. –

+0

@satch_boogie - я переформулировал запрос; посмотрите, работает ли он быстрее. –

+0

ничего себе! этот запрос завершен в течение <2 секунд на нескольких прогонах, этот запрос возвратил больше строк, чем запрос im, используя в настоящее время, но im проверяет результаты, если они соответствуют –

1

Я бы переписать этот запрос к этому:

SELECT radgroupreply.groupname, 
     count(distinct radusergroup.username ) AS users, 
     count(distinct CASE 
         WHEN radgroupreply.groupname <> 'Dropped Broadband Users' 
         THEN radusergroup.username 
      END) As users_without_dropped_broadband 
FROM radgroupreply     
JOIN radusergroup ON radgroupreply.groupname=radusergroup.groupname         
WHERE 
    (radgroupreply.groupname NOT LIKE 'FB-%' 
    AND radgroupreply.groupname <> 'Dropped Corporate Users') 
GROUP BY radgroupreply.groupname 
ORDER BY groupname asc 
; 

Приведенные выше отображает результаты запроса в несколько иной форме:

| gropname | users | users_without_dropped_broadband | 
| A  | 20 |        13 | 
| B  | 33 |        11 | 

, чем макет исходного запроса:

| gropname | users | 
| A  | 20 | 
| A  | 13 | 
| B  | 33 | 
| B  | 11 | 

но этот новый запрос выполняет все операции (читает таблицы, соединения, счетчики и т.д.) только один раз,
не в два раза, как ORYGINAŁ запроса, и должны быть по крайней мере на 50% быстрее (< 3,5 сек).

Смежные вопросы