下面的查询占用差不多7个而且我很困惑,如果它在mysqlserver(ndb存储引擎)中的正常行为,在解释输出它也表明它正在使用表索引
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 |
+----+--------------+---------------+-------+---------------+-----------+---------+----------------------------------+------+---------------------------------+
以下是join
中涉及的表的表结构和索引列信息表:radgroupreply; #total 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 :(得分:2)
由于您已GROUPing BY
列已将SELECT distinct(radgroupcheck.groupname)
更改为SELECT radgroupcheck.groupname
添加括号以澄清UNION
正在排序,而不仅仅是最后SELECT
:
( SELECT ... ) UNION ( SELECT ... ) ORDER BY ...
根据提示here更改many:many表(引擎除外)。
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
答案 1 :(得分: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 |
比oryginal查询的布局:
| gropname | users |
| A | 20 |
| A | 13 |
| B | 33 |
| B | 11 |
但是这个新查询执行所有操作(读取表格,联接,计数等)仅一次,不是原始查询的两倍,并且应该至少快50%( &lt; 3,5秒)。