当我们迈进计算机的大门,打下第一行代码,一直到完成一个应用,不可避免的一定会遇到同一个问题:数据存放在哪里?
可能你会觉得,你只是简单的写一个算法甚至只是一句赋值语句,并没有将数据保存下来,不需要考虑这个问题。事实上,此时的数据是保存在内存中的,计算机并不会在a=1
这句语句运行结束,就将a
的值给丢弃掉,而是暂存在内存中,等待程序员的使用。
1KB的数据如何存储,1MB的数据如何存储,乃至1GB,1TB的数据如何存储,以及存储的数据如何进行管理,都是个问题,尤其是数据逐渐多样化,不仅仅要存储数字、字符串、二进制等等。为了方便数据的存储管理,对数据进行组织,人们发明了数据库。MySQL就是一款广泛应用的数据库。
为了方便不同应用的使用,隔离不同应用或使用者,首先使用CREATE DATABASE 数据库名;
创建数据库。
接下来,对不同的数据组织,创建不同的数据表CREATE TABLE table_name (column_name column_type);
当创建数据表时,需要设定表名,列名,列的数据类型,还可以设定列的属性如非空NOT NULL
,自增IDAUTO_INCREMENT
,主键PRIMARY KEY
,唯一列UNIQUE
,引擎ENGINE
等。
针对不同场景为列设定不同的属性,可以加快查找效率,减少存储空间。
举一个创建数据表的例子:
CREATE TABLE IF NOT EXISTS `article`(
`id` INT UNSIGNED AUTO_INCREMENT,
`title` VARCHAR(100) NOT NULL
PRIMARY KEY ( `id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
数据最基本的操作就是CRUD,下面分别对应讲解一下如何在MySQL中进行CRUD。
MySQL的标准插入数据语法如下,其中的列和值是一一对应的。
INSERT INTO table_name ( 列1, 列2,...列N )
VALUES
( 值1, 值2,...值N );
MySQL的标准取出数据语法如下:
SELECT column_name,column_name
FROM table_name
[WHERE Clause]
[LIMIT N][ OFFSET M]
通常也会使用通配符*如SELECT * FROM ...
来取出所有的数据。SELECT语句可以说是使用最频繁的语句之一,通常为了加快取出的速度,还会使用索引。
MySQL的标准更新语句:
UPDATE table_name SET field1=new-value1, field2=new-value2
[WHERE Clause]
MySQL的标准删除语句:
DELETE FROM table_name [WHERE Clause]
建立索引的标准语法:
创建基本索引
CREATE INDEX indexName ON mytable(username(length));
修改表结构时添加索引
ALTER table tableName ADD INDEX indexName(columnName)
创建表时制定索引
CREATE TABLE mytable(
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
INDEX [indexName] (username(length))
);
索引的基本原理就是查找算法,回忆一下我们学过的查找算法,有二叉搜索树、Hash、二分查找法等。二分查找法在数据库中很少见,而Hash使用的也不多。最常见的是二叉搜索树的扩展——B树/B+树。
为什么不使用二叉搜索树呢,事实上,使用索引查找需要考虑到一个更加实际的问题,那就是访问硬盘的次数。由于内存不可能放下所有的数据,为了减少访问硬盘的次数,使用多叉树,保证叶子节点的高度一致,优点就在于每次查找的时间效率基本上是一致的,访问硬盘的次数也最少。
事实上,由于索引节点也占用空间,而自增主键的空间占用通常比使用字符串VARCHAR或我们自己指定的主键如用户身份证号、电话号码用的空间更小,所以使用自增主键作为索引是非常合适的。
世事无绝对,在具体的业务场景下,使用不同的最适合的索引,如联合索引等,才是最优的策略。
事务的概念包括ACID,也就是原子性、一致性、隔离性、持久性。
在MySQL中,事务通常是默认提交的,也可以使用SET AUTOCOMMIT=0
来禁止默认提交,但这样容易导致长事务等问题。
在MySQL中,事务处理的方式如下:
谈到事务,还要考虑事务的隔离级别,标准的隔离级别包括读未提交、读已提交、可重复读、串行化。
读未提交可能存在“脏读”的问题,即一个事务还未提交时,所做的变更可以被其他事务看到。读已提交可能导致“不可重复读”问题,即多次重复查询,可能得到不同的结果。可重复读则可能导致“幻读”问题,即按照相同的条件去执行,发现本来不存在的数据行出现了。
不可重复读和幻读的相似性较高,有时难以理解。注意,不可重复读重点在于update和delete,而幻读的重点在于insert。
事务的四个隔离级别读未提交、读已提交、可重复读、串行化是一级一级提升的,隔离级别高的会解决前面的隔离级别存在的问题。可串行化可以避免幻读的问题,通过强制事务串行执行,通常也会造成较大的开销,很少使用。
本文对MySQL的基本功能做了总结,但不够详细,详细的内容可以查找文档。