MySQL的使用技巧

GROUP BYGROUP_CONCATCONCAT元数据视图表备份表空间占用情况

欢迎来到 来到大浪涛天的博客

  • 一、MySQL的使用技巧
  • 1. GROUP BY的详细说明:
  • 2. GROUP_CONCAT的说明
  • 3. 关于多表查询连接规则
  • 4. 关于distinct去重的说明
  • 5. 关于MySQL的视图说明:
  • 6. MySQL的元数据的获取
  • 6-1. MySQL元数据介绍:
  • 6-2. information_schema的基本应用
  • 6-2-1. tables 视图的应用
  • 6-3. 重要的实例如下:
  • 6-3-1. 显示所有的库和表的信息
  • 6-3-2. 以以下模式 显示所有的库和表的信息
  • 6-3-3. 查询所有innodb引擎的表
  • 6-3-4. 统计world下的city表占用空间大小
  • 6-3-5. 统计world库数据量总大小
  • 6-3-6. 统计每个库的数据量大小,并按数据量从大到小排序
  • 6-3-7. 配合concat()函数拼接语句或命令
  • 6-4. show命令查看MySQL的元数据信息

一、MySQL的使用技巧

1. GROUP BY的详细说明:

GROUP BY 后接需要分组的列,添加该列执行后,数据库会先把该列的数据取出来先做一个排序,然后再去重,因此如果SELECT语句后面接着的该列如果没有被函数包裹进行运算或者没有GROUP_CONCAT做拼接的话会报错,这是为了保证查看的数据的完整性,如果不报错的话那去重后的值会丢失,这样显示的数据将没有任何意义,但这仅限于5.7的版本。
报错的本质是sql_mode开启了only_full_group_by的功能。

关于only_full_group_by的说明如下:

  1. 在5.7版本中MySQL sql_mode参数中自带,5.6和8.0都没有
  2. 在带有group by 字句的select中,select 后的条件列(非主键列),要么是group by后的列,要么需要在函数中包裹
  3. 如果需要开启或者关闭only_full_group_by则如下操作:
1. 查看该参数在sql_mode中是否存在或者开启
mysql> select @@sql_mode;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| @@sql_mode                                                                                                                                |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-------------------------------------------------------------------------------------------------------------------------------------------+
2. 在/etc/my.cnf中添加一行.
sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION 
3. systemctl restart mysqld3307.service 
4. 再次登陆到MySQL查看如下:
mysql> select @@sql_mode;
+------------------------------------------------------------------------------------------------------------------------+
| @@sql_mode                                                                                                             |
+------------------------------------------------------------------------------------------------------------------------+
| STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+------------------------------------------------------------------------------------------------------------------------+

2. GROUP_CONCAT的说明

group_concat配合group by使用是将直接将列转为行,因为group by后接着的列将会直接排序,去重(去重如果重复的列的多余的数据配合group_concat会转成行显示)。
列转行聚合函数,简单的事例如下:

mysql> SELECT user,host FROM mysql.user; (什么都没做,原本的数据)
+---------------+-------------+
| user          | host        |
+---------------+-------------+
| root          | 10.211.55.% |
| mysql.session | localhost   |
| mysql.sys     | localhost   |
| root          | localhost   |
+---------------+-------------+
4 rows in set (0.02 sec)

mysql> SELECT user,host FROM mysql.user GROUP BY user; (使用了GROUP BY对user列进行了排序并去重,结果是少了root的一行数据)
+---------------+-------------+
| user          | host        |
+---------------+-------------+
| mysql.session | localhost   |
| mysql.sys     | localhost   |
| root          | 10.211.55.% |
+---------------+-------------+
3 rows in set (0.01 sec)

mysql> SELECT user,GROUP_CONCAT(host) FROM mysql.user GROUP BY user; (在SELECT的后面对host列进行了GROUP_CONCAT拼接)
+---------------+-----------------------+
| user          | GROUP_CONCAT(host)    |
+---------------+-----------------------+
| mysql.session | localhost             |
| mysql.sys     | localhost             |
| root          | localhost,10.211.55.% |
+---------------+-----------------------+
3 rows in set (0.02 sec)

3. 关于多表查询连接规则

  1. 首先找涉及到的所有表
  2. 找到表和表之间的关联列
  3. 关联条件写在on后面
    A join B on 关联列
  4. 所有需要查询的信息放在select后
  5. 其他的过滤条件where group by having order by limit 网最后放
  6. select 执行顺序:select user ,count(name) from 表 where 列 group by user having 列 order by 列 ;
  7. 需要特别注意的是:对多表连接中,因为驱动表不走索引,所以一般数据行较少表放在左边作为驱动表。后续所有表的关联列尽量是主键或唯一键(表设计),至少建立一个索引。

4. 关于distinct去重的说明

MySQL中的distinct其实和SHELL里的uniq 一样的,直接在SELECT后跟着的列前面加上就可以直接去重,可以存在于函数包裹的括号里面。
例如:

mysql> SELECT count(distinct countrycode) from world.city;
+-----------------------------+
| count(distinct countrycode) |
+-----------------------------+
|                         232 |
+-----------------------------+
1 row in set (0.07 sec)
mysql> SELECT count( countrycode) from world.city;        
+---------------------+
| count( countrycode) |
+---------------------+
|                4079 |
+---------------------+

5. 关于MySQL的视图说明:

视图是一个虚拟表,是sql的查询结果,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据,在使用视图时动态生成。视图的数据变化会影响到基表,基表的数据变化也会影响到视图[insert update delete ] ; 创建视图需要create view 权限,并且对于查询涉及的列有select权限;使用create or replace 或者 alter修改视图,那么还需要改视图的drop权限。
简单的来说视图类式于Linux里面的SHELL脚本,先把复杂的命令写好,然后每次需要查询的时候直接拿出来进行执行。

mysql> create view unpass as SELECT t.tname as '教师名',GROUP_CONCAT(CONCAT(st.sname,":",s.score)) as '不及格的同学' FROM teacher as t JOIN course as c ON t.tno=c.tno JOIN score as s ON c.cno=s.cno JOIN student as st ON s.sno=st.sno WHERE s.score <60 GROUP BY t.tno;
mysql> use school;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from unpass;
+-----------+--------------------+
| 教师名    | 不及格的同学       |
+-----------+--------------------+
| hesw      | zhang3:59          |
| oldguo    | li4:40,zh4:40      |
+-----------+--------------------+

6. MySQL的元数据的获取

6-1. MySQL元数据介绍:

  1. 元数据是存储在"基表"中,不可以直接进行修改
  2. 通过专用的DDL语句,DCL语句进行修改
  3. 通过专用视图和命令进行元数据的查询
  4. information_schema中保存了大量元数据查询的试图
  5. show 命令是封装好功能,提供元数据查询基础功能

6-2. information_schema的基本应用

6-2-1. tables 视图的应用

information_schema库里面包含了大量已经做好了的视图,而tables表里面又包含了大量非常有用的东西,如下所示:

mysql> use information_schema;
mysql> desc tables;

TABLE_SCHEMA        表所在的库名
TABLE_NAME			表名
ENGINE				存储引擎
TABLE_ROWS			数据行
AVG_ROW_LENGTH		平均行长度
INDEX_LENGTH        索引长度

6-3. 重要的实例如下:

USE information_schema;
DESC TABLES;

6-3-1. 显示所有的库和表的信息
SELECT table_schema,table_name FROM information_schema.tables;
6-3-2. 以以下模式 显示所有的库和表的信息
world     city,country,countrylanguage

SELECT table_schema,GROUP_CONCAT(table_name) 
FROM information_schema.tables
GROUP BY table_schema;
6-3-3. 查询所有innodb引擎的表
SELECT table_schema,table_name ,ENGINE
FROM information_schema.tables 
WHERE ENGINE='innodb';
6-3-4. 统计world下的city表占用空间大小
表的占用空间大小的计算方式如下
表的数据量=平均行长度*行数+索引长度
表的真实数据量占用大小=AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH
SELECT table_name,(AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH)/1024
FROM information_schema.TABLES
WHERE table_schema='world' AND table_name='city';
如果不除以1024的话单位是字节,除以1024以后的单位是k
6-3-5. 统计world库数据量总大小
SELECT table_schema,SUM((AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH))/1024
FROM information_schema.TABLES
WHERE table_schema='world';
6-3-6. 统计每个库的数据量大小,并按数据量从大到小排序
SELECT table_schema,SUM((AVG_ROW_LENGTH*TABLE_ROWS+INDEX_LENGTH))/1024 AS total_KB
FROM information_schema.TABLES
GROUP BY table_schema
ORDER BY total_KB DESC ;
6-3-7. 配合concat()函数拼接语句或命令
  1. 如模仿以下语句,进行数据库的分库分表备份
    mysqldump -uroot -p123 world city >/bak/world_city.sql
SELECT
CONCAT("mysqldump -uroot -p123 ",table_schema," ",table_name
," >/bak/",table_schema,"_",table_name,".sql")
FROM information_schema.tables;
  1. 模仿以下语句,进行批量生成对world库下所有表进行操作
    ALTER TABLE world.city DISCARD TABLESPACE;
SELECT 
CONCAT("ALTER TABLE ",table_schema,".",table_name," DISCARD TABLESPACE;")
FROM information_schema.tables
WHERE table_schema='world';

注意这个语句删除当前.ibd文件,常用于.ibd文件已经备份,用来快速导入数据,步骤如下:

  • ALTER TABLE tbl_name DISCARD TABLESPACE;
  • 把备份的.ibd文件放回到恰当的数据库目录。
  • ALTER TABLE tbl_name IMPORT TABLESPACE;

6-4. show命令查看MySQL的元数据信息

show databases;        		查看数据库名
show tables; 		   		查看表名
show create database xx;  	查看建库语句
show create table xx;		查看建表语句
show processlist;			查看所有用户连接情况
show charset;				查看支持的字符集
show collation;				查看所有支持的校对规则
show grants for xx;			查看用户的权限信息
show variables like '%xx%'  查看参数信息
show engines;				查看所有支持的存储引擎类型
show index from xxx			查看表的索引信息
show engine innodb status\G 查看innoDB引擎详细状态信息
show binary logs 			查看二进制日志的列表信息
show binlog events in ''	查看二进制日志的事件信息
show master status ;		查看mysql当前使用二进制日志信息
show slave status\G 		查看从库状态信息
show relaylog events in ''	查看中继日志的事件信息
show status like ''			查看数据库整体状态信息