聚合与分组聚合
关于 COUNT 函数,总结如下:
- COUNT(n) 和 COUNT(*) 用于统计表中的总行数,不关心列值是否为 NULL
- COUNT(expr) 用于统计列值非 NULL 的行记录数
- COUNT(DISTINCT expr) 用于统计列值不同且非 NULL 的行记录数
1SELECT user_id, SUM(budget) FROM ad_unit WHERE unit_status = 0 GROUP BY user_id HAVING SUM(budget) > 5000;
很有用的条件判断函数与系统函数
1mysql> SELECT id, type, name, salary FROM worker;
2+----+------+--------+--------+
3| id | type | name | salary |
4+----+------+--------+--------+
5| 1 | A | tom | 1800 |
6| 2 | B | jack | 2100 |
7| 3 | C | pony | NULL |
8| 4 | B | tony | 3600 |
9| 5 | B | marry | 1900 |
10| 6 | C | tack | 1200 |
11| 7 | A | tick | NULL |
12| 8 | B | clock | 2000 |
13| 9 | C | noah | 1500 |
14| 10 | C | jarvis | 1800 |
15+----+------+--------+--------+
IF 条件判断函数
1mysql> SELECT name, IF(type='A', '研发', '非研发') AS type FROM worker WHERE id IN (1, 2);
2+------+-----------+
3| name | type |
4+------+-----------+
5| tom | 研发 |
6| jack | 非研发 |
7+------+-----------+
8
9
10mysql> SELECT name, IFNULL(salary, 0) AS salary FROM worker WHERE id IN (1, 2, 3);
11+------+--------+
12| name | salary |
13+------+--------+
14| tom | 1800 |
15| jack | 2100 |
16| pony | 0 |
17+------+--------+
CASE 条件判断函数
1CASE expr
2 WHEN v1 THEN r1
3 ......
4 WHEN vx THEN rx
5 ELSE rn
6END
1mysql> SELECT
2 -> name,
3 -> (CASE type
4 -> WHEN 'A' THEN '研发'
5 -> WHEN 'B' THEN '测试'
6 -> WHEN 'C' THEN '运维'
7 -> ELSE '其他'
8 -> END) AS type
9 -> FROM
10 -> worker
11 -> WHERE
12 -> id IN (
13 -> 1, 2, 3
14 -> );
15+------+--------+
16| name | type |
17+------+--------+
18| tom | 研发 |
19| jack | 测试 |
20| pony | 运维 |
21+------+--------+
系统函数
1
2SELECT VERSION(); // MySQL 服务器版本
3
4SELECT CONNECTION_ID(); // 查询客户端连接 ID
5
6
7mysql> SELECT * FROM information_schema.PROCESSLIST;
8+----+------+-----------------+--------------------+---------+------+-----------+----------------------------------------------+
9| ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO |
10+----+------+-----------------+--------------------+---------+------+-----------+----------------------------------------------+
11| 4 | root | localhost | imooc_mysql | Query | 0 | executing | SELECT * FROM information_schema.PROCESSLIST |
12| 2 | root | localhost:50675 | imooc_mysql | Sleep | 27 | | NULL |
13| 5 | root | localhost:58433 | information_schema | Sleep | 67 | | NULL |
14| 3 | root | localhost:50676 | NULL | Sleep | 26 | | NULL |
15| 6 | root | localhost:58446 | NULL | Sleep | 38 | | NULL |
16+----+------+-----------------+--------------------+---------+------+-----------+----------------------------------------------+
17
18mysql> SELECT THREAD_ID, NAME, TYPE, PROCESSLIST_ID FROM performance_schema.threads WHERE PROCESSLIST_ID = 4;
19+-----------+---------------------------+------------+----------------+
20| THREAD_ID | NAME | TYPE | PROCESSLIST_ID |
21+-----------+---------------------------+------------+----------------+
22| 30 | thread/sql/one_connection | FOREGROUND | 4 |
23+-----------+---------------------------+------------+----------------+
24
25
26SELECT CHARSET('慕课网'), CHARSET('MySQL');
27
28select COLLATION('MySQL'), COLLATION(CONVERT('MySQL' USING gbk));
29
30SELECT LAST_INSERT_ID();
通过 SHOW PROCESSLIST 和 SHOW FULL PROCESSLIST 语句也可以查看连接信息
SHOW PROCESSLIST 只会打印前 100 条连接信息,而 SHOW FULL PROCESSLIST 正如它的名字一样,可以打印全部的连接信息
- Id:用户客户端连接 MySQL 时,系统自动分配的连接 ID
- User:当前连接的用户名
- Host:当前用户的 id 和 端口号
- db:当前连接选择的数据库,如果没有选择,则是 NULL
- Command:当前连接执行的命令,取值为 Sleep(睡眠)、Query(查询)、Connect(连接)
- Time:状态持续的时间,单位是秒
- State:当前连接执行 SQL 语句的状态
- Info:显示当前执行的 SQL 语句
用户与权限
1CREATE USER 'imooc-1'@'localhost' IDENTIFIED BY 'imooc';
2
3GRANT ALL PRIVILEGES ON *.* TO 'imooc-2'@'localhost' IDENTIFIED BY 'imooc';
4FLUSH PRIVILEGES;
5
6
7 -- 授予所有的权限
8GRANT ALL PRIVILEGES ON *.* TO 'USERNAME'@'HOST';
9
10-- 授予某个库所有表的所有权限
11GRANT ALL PRIVILEGES ON DB_NAME.* TO 'USERNAME'@'HOST';
12
13-- 授予某个库所有表的 SELECT、UPDATE 权限
14GRANT SELECT, UPDATE ON DB_NAME.* TO 'USERNAME'@'HOST';
15
16-- 授予某个库下某个表的 INSERT 权限
17GRANT INSERT ON DB_NAME.TABLE_NAME TO 'USERNAME'@'HOST';
18
19-- 授予某个库下某个表的某个列的 UPDATE 权限
20GRANT UPDATE(COLUMN_NAME) ON DB_NAME.TABLE_NAME TO 'USERNAME'@'HOST';
21
22-- 授予某个库下创建、修改、删除表结构的权限
23GRANT CREATE ON DB_NAME.* TO 'USERNAME'@'HOST';
24GRANT ALTER ON DB_NAME.* TO 'USERNAME'@'HOST';
25GRANT DROP ON DB_NAME.* TO 'USERNAME'@'HOST';
26
27-- 撤销某个库下某个表的 DROP 权限
28REVOKE DROP ON DB_NAME.TABLE_NAME FROM 'USERNAME'@'HOST';
29
30-- 撤销某个库下某个表的所有权限
31REVOKE ALL ON DB_NAME.TABLE_NAME FROM 'USERNAME'@'HOST';
32
33SHOW GRANTS FOR 'imooc-1'@'localhost';
数据备份与恢复
这里只介绍mysqldump工具
1# 导出 imooc_mysql 库的所有数据,如果有更多的库,空格隔开即可
2mysqldump -uroot -proot --databases imooc_mysql > ~/QinyiZhang/mysql_backup_data/imooc_mysql.sql
3
4# 导出 imooc_mysql 库中的 worker 表数据,如果有更多的表,空格隔开即可
5# 需要注意,导出指定表只能针对一个库,且导出指定表的 SQL 中没有创建库的语句,只有删除表、创建表、插入数据
6mysqldump -uroot -proot --databases imooc_mysql --tables worker > ~/QinyiZhang/mysql_backup_data/imooc_mysql_worker.sql
7
8# 导出 imooc_mysql 库中 worker 表 id > 5 的数据(字段是数字类型)
9# 这也被称为条件导出,如果有多个表的条件相同,则可以同时导出多个表
10mysqldump -uroot -proot --databases imooc_mysql --tables worker --where='id > 5' > ~/QinyiZhang/mysql_backup_data/imooc_mysql_worker_id_greater_5.sql
11
12# 导出 imooc_mysql 库中 worker 表 type = B 的数据(字段是字符类型)
13mysqldump -uroot -proot --databases imooc_mysql --tables worker --where="type = 'B'" > ~/QinyiZhang/mysql_backup_data/imooc_mysql_worker_type_equal_B.sql
14
15# 只导出 imooc_mysql 库中 worker 表结构,不导出数据
16mysqldump -uroot -proot --no-data --databases imooc_mysql --tables worker > ~/QinyiZhang/mysql_backup_data/imooc_mysql_worker_only_table.sql
mysqldump 提供了 –single-transaction 选项。使用这个选项会在导出数据之前提交一个 BEGIN SQL 语句,即把备份操作放在一个事务中去执行,不会阻塞任何应用程序且能保证导出时数据库的一致性状态。
1mysqldump --single-transaction -uroot -proot --databases imooc_mysql > ~/QinyiZhang/mysql_backup_data/imooc_mysql_single_transaction.sql
2# mysqldump 还有一个非常重要的选项:-F,它将在导出数据之后生成一个新的 binlog 文件
3mysqldump --single-transaction -uroot -proot --databases imooc_mysql -F > ~/QinyiZhang/mysql_backup_data/imooc_mysql_new_binlog.sql
恢复数据
mysql -uroot -proot imooc_mysql < ~/QinyiZhang/mysql_backup_data/imooc_mysql_worker.sql
事务隔离级别
- READ-UNCOMMITTED:它是最低的隔离级别,正如它的名称一样,它允许一个事务读取其他事务未提交的数据。这个隔离级别很少在工业环境中应用,因为它的性能并不会比其他高级别的性能好很多
- READ-COMMITTED:它可以保证一个事务修改的数据提交之后才能被其他的事务读取。这个隔离级别是大多数数据库系统的默认隔离级别,但并不是 MySQL 默认的
- REPEATABLE-READ:它的核心在于 “可重复”,即在一个事务内,对同一字段的多次读取结果都是相同的,也是 MySQL 的默认事务隔离级别
- SERIALIZABLE:它是最高的隔离级别,花费的代价也是最高的,事务的处理是顺序执行的。在这个级别上,可能会导致大量的锁超时现象和锁竞争。同样,在工业级环境中,很少被使用
1-- global.tx_isolation 代表系统级的隔离级别,即对所有的会话都生效
2-- tx_isolation 代表会话级隔离级别,只对当前会话生效
3mysql> SELECT @@global.tx_isolation, @@tx_isolation;
4+-----------------------+-----------------+
5| @@global.tx_isolation | @@tx_isolation |
6+-----------------------+-----------------+
7| REPEATABLE-READ | REPEATABLE-READ |
8+-----------------------+-----------------+
9
10-- 查看默认的 SQL 语句自动提交
11mysql> SHOW VARIABLES LIKE 'autocommit';
12+---------------+-------+
13| Variable_name | Value |
14+---------------+-------+
15| autocommit | ON |
16+---------------+-------+
17
18-- 关闭自动提交
19mysql> SET autocommit = off;
20
21-- 检验自动提交是否已关闭
22mysql> SHOW VARIABLES LIKE 'autocommit';
23+---------------+-------+
24| Variable_name | Value |
25+---------------+-------+
26| autocommit | OFF |
27+---------------+-------+
- start transaction:显式地开启一个事务
- commit:提交事务,使得对数据库做的所有修改成为永久性
- rollback:回滚结束用户的事务,并撤销正在进行的所有未提交的修改
通过锁解决并发数据
不通过索引条件查询时,InnoDB 一定会使用表锁,而不是行锁(因为没有索引只能全表扫描)
查询时,不论是使用主键索引、唯一索引或者普通的索引,InnoDB 都会使用行锁来对数据加锁
索引定义及其优化
索引的优点:
- 减少扫描的数据量,加速查询
- 减少或完全消除数据库的排序操作(ORDER BY),因为索引是有序的
- 将服务器的随机 IO 变为顺序 IO,例如,想要查询 salary 处于 1500 ~ 2100 的员工,就可以按照索引顺序查询
索引的缺点:
- 索引会占据额外的存储空间(毕竟它是数据结构),包括磁盘和内存
- 由于对数据需要排序,自然会影响到数据更新(插入、更新、删除)的速度
- 几乎任何技术或优化都具有两面性,有优点,自然也就会有缺点。所以,索引虽好,不要滥用。一定要在足够理解索引和业务的基础之上再去选择创建索引、使用索引。
叶子结点才存储数据,页与页之间是双链表
查看索引占据的空间大小
MySQL 服务器所有索引占据的空间
1mysql> SELECT CONCAT(ROUND(SUM(index_length) / (1024*1024), 2), ' MB') FROM information_schema.TABLES;
2+---------------------------------------------------------+
3| CONCAT(ROUND(SUM(index_length) / (1024*1024), 2), ' MB') |
4+---------------------------------------------------------+
5| 0.26 MB |
6+---------------------------------------------------------+
单独查询一个库或一个表占据的索引空间
1mysql> SELECT
2 -> CONCAT(ROUND(SUM(index_length) / (1024*1024), 2), ' MB')
3 -> FROM
4 -> information_schema.TABLES
5 -> WHERE
6 -> TABLE_SCHEMA = 'imooc_mysql';
7+----------------------------------------------------------+
8| CONCAT(ROUND(SUM(index_length) / (1024*1024), 2), ' MB') |
9+----------------------------------------------------------+
10| 0.03 MB |
11+----------------------------------------------------------+
12
13mysql> SELECT
14 -> CONCAT(ROUND(SUM(index_length) / (1024*1024), 2), ' MB')
15 -> FROM
16 -> information_schema.TABLES
17 -> WHERE
18 -> TABLE_SCHEMA = 'imooc_mysql'
19 -> AND TABLE_NAME = 'worker';
20+----------------------------------------------------------+
21| CONCAT(ROUND(SUM(index_length) / (1024*1024), 2), ' MB') |
22+----------------------------------------------------------+
23| 0.03 MB |
24+----------------------------------------------------------+