基础概念
参考:《深入浅出MySQL》
SCHEMA
schema 为数据库对象的集合, schema里面包含了各种对象如tables, views, sequences, 可以视作”数据库”, show database
可以看到schema.
不同数据库产品的schema概念是不同的:
- MySQL: Schema 等同于 Datebase
- SQL Server: schema中包含了数据库的表,字段,数据类型以及主键和外键的名称。
数据类型
- 数字:
- 整数:
- TINYINT 1, SMALLINT 2, INT 4, BIGINT 8
- 小数:
- 浮点数: float, double
- 定点数: decimal, 常用来表示高精度数据, 比如货币
- 整数:
- 字符串:
- CHAR 255, 定长
- VARCHAR 65535, 变长
- TEXT: 还分为TEXT(65535), MEDIUMTEXT, LONGTEXT
- BOLB: 还分为BOLB(65535), MEDIUMBOLB, LONGBOLB, 与TEXT的区别是, BOLB可以存储二进制数据, 比如图片
- 日期:
- DATE: 2017-07-25
- DATETIME: 2017-07-25 21:57
- TIMESTAMP: 字符串的”2017-07-25 21:57”
DATETIME 和 TIMESTAMP类型的区别:
- DATETIM 和 TIMESTAMP类型所占的存储空间不同,前者8个字节,后者4个字节,这样造成的后果是两者能表示的时间范围不同。
- 前者范围为 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59,后者范围为 1970-01-01 08:00:01到2038-01-19 11:14:07。所以可以看到TIMESTAMP支持的范围比DATATIME要小,容易出现超出的情况.
- TIMESTAMP类型在默认情况下,insert、update 数据时,TIMESTAMP列会自动以当前时间(CURRENT_TIMESTAMP)填充/更新。@ref: MySQL timestamp自动更新时间分享
- TIMESTAMP比较受时区timezone的影响以及MYSQL版本和服务器的SQL MODE的影响
运算符
符号 | 描述 | 备注 |
---|---|---|
= | 等于 | |
> | 大于 | |
\< | 小于 | |
!= | 不等于 | 不可比较NULL, 例 1 != NULL也返回NULL |
<> | 不等于 | 同上 |
<=> | 等于 | NULL-Safe的比较, NULL<=>NULL为1, 1<=>NULL为0 |
IS NULL | 等于NULL | |
IS NOT NULL | 不等于NULL | |
BETWEEN | 在两值之间 | |
IN | 在集合中 | |
LIKE | 模糊匹配 |
函数
- 字符串拼接: CONCAT(s1, s2, …)
- LOWER(s1), UPPER(s1)
- FLOOR(a): 返回小于a的最大整数
- MOD(a,b): 返回x/y的模
字符集(编码)
查看数据库使用的字符集:
# 方式1 |
GBK
vs UTF-8
- GBK: 扩展了GB2312标准, 无论英文还是汉字都是2字节
- UTF-8: 英文1字节, 汉字3字节, 同时也兼容ASCII码
- 如果数据库只需要支持一般中文,数据量很大,性能要求也很高,那就应该选择双字节定长编码的中文字符集,比如 GBK。 相对于UTF-8而言,GBK比较“小”,每个汉字只占2个字节,而 UTF-8汉字编码需要3个字节,这样可以减少磁盘I/O、数据库Cache以及网络传输的时间,从而提高性能。
- 如果应用主要处理英文字符,仅有少量汉字数据,那么选择 UTF-8更好,因为UTF-8的西文占1字节, 而GBK西文字符编码都是2个字节(汉字3字节),会造成很多不必要的开销。
utf8
vs utf8mb4
- utf8 表示西文需2字节, 汉字需3字节, 如果在utf8编码上使用
vchar(100)
这种类型, Mysql会为该列保留 “一个utf8最大占用空间x100” 也即 300字节. - utf8 存在的问题: uft8最大能编码的Unicode范围是3字节, 对于超过3字节的无能为力(包括一些汉字, 以及emoji表情)
- utf8mb4 (后缀mb4意思是”most bytes 4”), “4字节 UTF-8 Unicode 编码”, utf8mb4可以最多表示4字节Unicode编码, utf8是utf8mb4的一个子集, utf8mb4使用与utf8相同的编码值和长度, 此外utf8mb4还包括utf8没有的4字节编码, 因此从旧版本的MySQL UTF8 升级数据时 不用担心字符转换或丢失数据
@ref 全面了解mysql中utf8和utf8mb4的区别 - 谢思华blog - OSCHINA
主键 & 外键
主键: 一个表只能有一个列作为主键, 主键的值不可重复, 不可为空(NULL)
- 主键一定是唯一性索引,唯一性索引并不一定就是主键
外键: 一个表中的FOREIGN KEY 指向另一个表中的 PRIMARY KEY。
- FOREIGN KEY 约束用于预防破坏表之间连接的动作。
- FOREIGN KEY 约束也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。
- 外键约束:
- (1)插入非空值时,如果主键值中没有这个值,则不能插入。
- (2)更新时,不能改为主键表中没有的值。
- (3)删除主键表记录时,可以在建外键时选定外键记录一起联删除还是拒绝删除。
- (4)更新主键记录时,同样有级联更新和拒绝执行的选择。
@ref: 大家设计数据库时使用外键吗? - 知乎
互联网行业应用不推荐使用外键: 用户量大,并发度高,为此数据库服务器很容易成为性能瓶颈,尤其受IO能力限制,且不能轻易地水平扩展;若是把数据一致性的控制放到事务中,也即让应用服务器承担此部分的压力,而引用服务器一般都是可以做到轻松地水平的伸缩;
所以Hibernate多对一(many-to-one)/一对多(one-to-many)关联
也就很少提及了。
索引
① 按照索引的物理存储来分:
- 聚集索引 (clustered index):聚集索引决定数据在磁盘上的物理排序,一个表只能有一个聚集索引,一般用primary key来约束。主键索引对应的B+树, 叶子节点是一行的完整数据
- 非聚集索引 (non-clustered index):它并不决定数据在磁盘上的物理排序,其叶子节点的数据是主键的值。所以使用普通索引查询的时候,需要先找到对应的主键值,再回主键索引的B+树上找到行数据(回表)
② 从逻辑角度, MySQL一共有五类索引:
- 唯一索引(UNIQUE INDEX), 唯一索引是不允许其中任何两行具有相同索引值的索引。主键是一种唯一性索引,它必须指定为“PRIMARY KEY”
- 主键索引:主键索引是一种特殊的唯一索引,不允许有空值, 主键索引也是聚簇索引
- 普通索引:非主键索引, 最基本的索引类型,没有唯一性之类的限制。
- 联合索引:指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用联合索引时遵循最左前缀集合
注意:建了一个(a,b,c)的联合索引,那么实际等于建了(a),(a,b),(a,b,c)三个索引,每多一个索引都会增加写操作的开销和磁盘空间的开销。 - 候选索引:与主索引一样要求字段值的唯一性,并决定了处理记录的顺序。在数据库和自由表中,可以为每个表建立多个候选索引。
- 空间索引:空间索引是对空间数据类型的字段建立的索引,MYSQL中的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING、POLYGON。
MYSQL使用SPATIAL关键字进行扩展,使得能够用于创建正规索引类型的语法创建空间索引。创建空间索引的列,必须将其声明为NOT NULL,空间索引只能在存储引擎为MYISAM的表中创建
③ 从数据结构角度:
- BTREE索引: MyISAM和InnoDB存储引擎默认都是BTREE索引
- HASH索引:
- 仅仅能满足”=”,”IN”和”<=>”查询,不能使用范围查询
- 其检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引
- 只有Memory存储引擎显示支持hash索引
- FULLTEXT索引: 全文索引,在 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。FULLTEXT索引也是按照分词原理建立索引的。
- RTree索引(空间索引):空间索引是MyISAM的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少,不做特别介绍。
MySQL引擎
- InnoDB
- 支持事务
- 支持行级锁
- MyISAM
- 不支持事务
- 支持表锁, 不支持行级锁 // 并发性能差
- 设计简单,某些场景下性能很好,例如获取整个表有多少条数据
count(*)
,性能很高。
- Memory
- 不支持事务
- 支持哈希索引
MySQL Commands
连接
mysql -h 127.0.0.1 -u xxx -pXXX -P 3306 |
导出
- 导出数据库结构,不带数据:
mysqldump -h ip_addr -uxxx -pxxx -d DBName > dump.sql
- 如果要一并导出数据, 去掉
-d
参数. - 导出表, 不带数据:
mysqldump -h ip_addr -uxxx -pxxx -d DBName TableName > dump.sql
导入
mysql -u username -p -h localhost DATABASE-NAME < data.sql
mycli
安装:
pip install mycli |
或:
brew update && brew install mycli |
Usage:
# 获取帮助 |