mysql5.7版本的压缩包下载链接
链接: https://pan.baidu.com/s/1qCxsisX_IDs-1j19fiLpzg提取码: ktm5
[mysqld]
basedir=D:\mysql-5.7.23\
datadir=D:\mysql-5.7.23\data\
port=3306
skip-grant-tables #初次登录不用输入密码
CREATE TABLE IF NOT EXISTS `student` (
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`pwd` VARCHAR(20) NOT NULL DEFAULT '123456' COMMENT '密码',
`sex` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT '性别',
`birthday` DATETIME NULL COMMENT '出生日期',
`address` VARCHAR(100) DEFAULT NULL COMMENT '家庭住址',
`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- 数据库引擎
INNODB -- 默认使用
MYISAM -- 早些年使用
--
数据库引擎 | INNODB | MYISAM |
---|---|---|
事务 | 支持 | 不支持 |
数据行锁定 | 支持 | 不支持 |
外键约束 | 支持 | 不支持 |
全文索引 | 不支持 | 支持 |
表空间的大小 | 较大,约为2倍 | 较小 |
ALTER TABLE `teacher` RENAME AS `teacher1` -- 修改表名
ALTER TABLE `teacher1` ADD age INT(11) -- 增加表字段
ALTER TABLE `teacher1` MODIFY age VARCHAR(10) -- 修改表字段约束
ALTER TABLE `teacher1` CHANGE age age1 INT(2) -- 修改表字段名称
ALTER TABLE `teacher1` DROP age1 -- 删除表字段
DROP TABLE IF EXISTS `teacher1` -- 删除表
ALTER TABLE `student` ADD gradeid INT(2)
CREATE TABLE `grade` (
`gradeid` INT(2) PRIMARY KEY NOT NULL AUTO_INCREMENT COMMENT '年级id',
`name` VARCHAR(10) NOT NULL COMMENT '年级名称'
)ENGINE=INNODB DEFAULT CHARSET=utf8
ALTER TABLE `student`
ADD CONSTRAINT `FK_gradeid` FOREIGN KEY(`gradeid`) REFERENCES `grade`(`gradeid`)
阿里 规范不允许使用 外键 级联,这样会使数据库操作极为麻烦
要求 外键的关系 在应用层去解决 即java代码中去解决
DDL 定义
DML 管理
DQL 查询
DCL 控制
insert into 表名(列名1, 列名2, 列名3)
values ('值1','值2','值3'),
('值1','值2','值3')
update 表名
set 列名1 = '值1',
列名2 = '值2',
列名3 = '值3'
where 条件
delete from 表名
where 条件
#concat() 拼接函数
select concat(a, b) [as '别名']
from 表名 [as '别名']
[where 条件]
join on # 连接查询
where # 等值查询
操作 | 描述 |
---|---|
inner join | 查询两张表中任一表包含的 目标字段值 |
left join | 返回左表包含的 目标字段值 即使右表中 不含该记录 |
right join | 返回右表包含的 目标字段值 即使左表中 不含该记录 |
select 语法
select [all | distinct]
{* | table.* | [table.field1[as alias1][,table.field2[as alias2]][,...]]}
from table_name [as table_alias]
[left | right | inner join table_name2] -- 联合查询
[where ...] -- 指定结果需满足的条件
[group by ...] -- 指定结果按照哪几个字段来分组
[having ...] -- 过滤分组的记录必须满足的次要条件
[order by ...] -- 指定查询记录按一个或多个条件排序
[limit {[offset,]row_count | row_countOFFSET offset}] ;
-- 指定查询的记录从哪条到哪条
注意:[ ]括号代表可选的,{ }括号代表必选的
group by 后的条件过滤只能用having 不能用where
CREATE DATABASE shop CHARACTER SET utf8 COLLATE utf8_general_ci
USE shop
CREATE TABLE `account` (
`id` INT(3) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
`money` DECIMAL(9,2) NOT NULL,
PRIMARY KEY(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8
INSERT INTO `account`(`name`, `money`) VALUES ('A', 800.00),('B', 200.00)
UPDATE `account` SET `money` = 2000.00 WHERE id = 1
UPDATE `account` SET `money` = 10000.00 WHERE id = 2
SET autocommit = 0; -- 关闭自动提交
START TRANSACTION -- 开始一个事务 (一组事务)
UPDATE `account` SET `money` = `money` - 500 WHERE `name` = 'A'; -- A减500
UPDATE `account` SET `money` = `money` + 500 WHERE `name` = 'B'; -- B加500
COMMIT -- 提交
ROLLBACK -- 回滚
SET autocommit = 1; -- 恢复自动提交
要素 | 特点 |
---|---|
原子性(automicity) | 事务内部的操作不可分割, 全成功(commit)或全失败(rollback) |
一致性 (consistency) | 事务的前后,整体状态保持一致 (如事务前A,B共12000,事务后也必须12000) |
隔离性 (isolation) | 事务与事务之间,应相互隔离执行互不影响 (避免 xxx读) |
持久性 (durability) | 事务一旦提交,则数据永久化 |
一个事务读取了另一个事务还未提交的数据
一个事务内 多次读取 发现 有数据被其他事务修改过
一个事务内 多次读取 读到了另一个事务插入的新数据
alter table 表名 add fulltext index 索引名(列名);
explain select * from student -- explain关键字分析sql执行情况
explain select * from student where match('studentname') against('刘');
建表
drop table if exists `app_user`;
CREATE TABLE `app_user` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT '',
`eamil` varchar(50) NOT NULL,
`phone` varchar(20) DEFAULT '',
`gender` tinyint(4) unsigned DEFAULT '0',
`password` varchar(100) NOT NULL DEFAULT '',
`age` tinyint(4) DEFAULT NULL,
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `id_app_user_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=1000002 DEFAULT CHARSET=utf8
创建插入100万行随机数据的函数
DELIMITER $$
USE `school`$$ -- 注意要有这个数据库
DROP FUNCTION IF EXISTS `mock_data`$$
CREATE DEFINER=`root`@`localhost` FUNCTION `mock_data`() RETURNS INT(11)
BEGIN
DECLARE num INT DEFAULT 1000000;
DECLARE i INT DEFAULT 0;
WHILE i<num DO
INSERT INTO `app_user`(`name`,`eamil`,`phone`,`gender`,`password`,`age`)
VALUES (CONCAT('用户',i),'[email protected]',CONCAT('18',FLOOR(RAND()*(999999999-100000000)+100000000))
,FLOOR(RAND()*2),UUID(),FLOOR(RAND()*100));
SET i=i+1;
END WHILE;
RETURN i;
END$$
DELIMITER ;
测试效果
SELECT * FROM app_user WHERE `name` = '用户9999'; -- 1.148 sec
SELECT * FROM app_user WHERE `name` = '用户9999'; -- 1.283 sec
SELECT * FROM app_user WHERE `name` = '用户9999'; -- 1.222 sec
EXPLAIN SELECT * FROM app_user WHERE `name` = '用户9999'; -- 找了992391条数据才找到 无索引
CREATE INDEX id_app_user_name ON app_user(`name`); -- 创建一个索引 11.674 sec
SELECT * FROM app_user WHERE `name` = '用户9999'; -- 执行耗时: 0 sec 传送时间: 0.002 sec 总耗时: 0.002 sec 建立索引后
grant all privileges *.* to kuangshen -- 授予所有权限 但不包含 grant option
revoke all privileges *.* from kuangshen -- 撤销所有权限
导出:mysqldump -h主机名 -u用户名 -p密码 数据库名 表名(多个时空格隔开) > 磁盘位置+文件名.sql
mysqldump -hlocalhost -uroot -p123456 school student > D:/a.sql
导入:source 磁盘位置+文件名.sql
# 先链接数据库
mysql -uroot -p123456
#使用数据库
use school
#执行表的导入
source D:/a.sql
#还可以直接来
mysql -uroot -p123456 school < D:/a.sql
1.分析需求
2.落实实体表
3.分析实体表之间的关系
第一范式(1NF)
原子性: 保证每一列的含义不可再分 (家庭信息:(地址,人口数 ) -> 分为 2列才对)
第二范式(2NF)
前提:满足 第一范式
每张表只描述一件事情 。。。。。。
第三范式(3NF)
前提:满足 第一范式 和 第二范式
消除列之间的传递依赖
可以直观的感受到 范式会导致表的疯狂细分
实际生产环境 规范性和性能问题
阿里标准: 关联查询的表不得超过三张
以用户体验和性能为主 适当考虑 范式
例如: 某些冗余列 可以 消除 多表链接查询
学习文章http://blog.codinglabs.org/articles/theory-of-mysql-index.html
然后磁盘读写会具有一些特质。
磁盘I/O, 由磁头和磁盘来完成,磁头读取磁盘的信息。
这二个动作是产生磁盘I/O时,会发生在机器上的物理动作,所以相对而言会非常耗时。
B-Tree和B+Tree的区别(对着图看还挺直观的)
然后数据库或文件系统采用B+Tree实现索引的时候,会再做一点修改,在叶节点之间添加顺序访问指针
BTree这样的结构,就刚好可以,把叶节点的大小设置为磁盘扇区 页 的大小,这样吻合后,一个叶节点中值的访问,就只需要一次I/O操作了
MyISAM的B+Tree实现,叶节点中data存储的是真实数据区的内存地址,索引得到的结果是目标值的内存地址,然后需要到对应地址获取值。
InnoDB的B+Tree实现,叶节点中data域保存了完整的数据记录,当前索引的key就是数据表的主键,
因此InnoDB表数据文件本身就是主索引。
所以,mysql数据库 使用InnoDB引擎创建的数据库,里面的数据表必须要有主键,不显示的设置主键,也会底层默认使用一个唯一列来作为主键。
上面所说的一堆特性, 应用起来表示为
一定要让每个表的索引都建立在一个 自增的主键列上,这样才能有效利用 局部性原理 提高读写效率。
另外索引是一个独立存在的结构,也会占用内存,所以不要使用过长的数据列建立索引,若有必要,就采用最左前缀去创建索引,这个前缀的长度,需要根据 选择性 来确定
Index Selectivity = Cardinality / #T
显然选择性的取值范围为(0, 1],选择性越高的索引价值越大,这是由B+Tree的性质决定的
SELECT count(DISTINCT(title))/count(*) AS Selectivity FROM employees.titles;
另外说一些,索引失效的场景