2019年5月6日 晚上,MySQL数据库学习第一节课:
MySQL学习内容如下:
1 mysql的介绍
2 sql语句,增删改查 CURD
3 索引以及原理
4 事务处理
5 存储引擎
------------------------------------------------分割线-------------------------------------------------------
使用数据库的优点:
1、可以(像文件一样)实现数据持久化到本地
2、使用完整的管理系统统一管理数据,易于查询
上面第一点的原因:实际上是借助于DBMS来将数据最终存储到磁盘上的文件。
数据库的相关概念:
DB:数据库,存放数据的仓库(容器),它保存了一系列有组织,比较规范的数据。
DBMS:数据库管理系统(简称:数据库软件、数据库产品。如MySQL)。数据库是通过DBMS创建和操作的容器,DBMS用来管理DB中的数据。(DBMS用于创建和管理DB)
上面二者关系,如下图所示:
SQL:结构化查询语言,专门用来与数据库管理系统通信的语言。
SQL的优点:
数据库的特点:
DBMS分为两大类:
------------------------------------------------分割线-------------------------------------------------------
MySQL现隶属于 oracle公司
1 它是关系型数据库的一种。
2 它是个RDBMS 关系型数据库管理系统=》创建很多数据库 =》二维表
SQL(Structed Query Language)语句
二维表 行:记录 列:属性/字段
关系型数据库有:(常见的数据库管理系统)
oracle:贵
MySQL: 企业版(收费的) 社区版(免费的) MySQL
SQL Server 其最大的缺点:只能安装在Windows上
DB2(IBM公司):其稳定性 性能上不错的,适合于处理海量数据
非关系型数据库 NoSQL [key, value] 有:
1 memcached(不能持久化)
2 redis(可以持久化数据)缓存数据库
可以看一下MySQL在市场上的应用比例:
MySQL产品的特点: 优点:
------------------------------------------------分割线-------------------------------------------------------
关系型数据库:指采用了关系模型来组织数据的数据库,而关系模型指的就是二维表模型,而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。
关系型数据库的优势:
非关系型数据库,又被称为NoSQL(Not Only SQL )意为不仅仅是SQL,指非关系型的,分布式的,且一般不保证遵循ACID原则的数据存储系统。
非关系型数据库以键值对
------------------------------------------------分割线-------------------------------------------------------
打开注册表:regedit (cmd里面)
------------------------------------------------分割线-------------------------------------------------------
MySQL:为什么说它是分布式的关系型数据库管理系统?
答:它不是一个单机的数据库,mysql client和mysql server,所以在使用的时候 需要安装client 和 server,server比较重要(数据存储的地方)。所以说 常说的安装数据库指的是 安装server端。
mysql client:api接口 适用于c&c++ java python php go
mysql server作为一个网络服务器,采用得网络模型是:
select + 线程池得模型 >> 磁盘得I/O速率
question:采用得网络模型是:epoll + 线程池得模型 ?
因为:>> 磁盘得I/O速率,最好的不一定是最合适的。
linux:epoll windows:iocp
------------------------------------------------分割线-------------------------------------------------------
在服务端安装好了以后,这里面就相当于 维护了一个大容器(大仓库),但是可能默认是关闭状态,即使有权限和身份 也是进不去的。所以在使用前,需要保证服务是启动的状态。
windows上在任务管理器 - 服务 - 启动 MySQL(安装时 的服务名)
上面的打开服务,略显太慢。
以管理员身份打开DOS,然后net start mysql启动服务:
接下来关闭服务:net stop mysql
打开mysql command line - unicode命令行窗口输入密码就可以登录MySQL server
上面这种登录方式 只适合root用户,下面一种也是可以的(Windows的命令提示符 管理员运行 ):(这样也可以显示密码登录)
linux先启动mysqld /etc/init.d/mysqld start/stop/restart
netstat -tanp 查看以下mysqld服务是否启动成功
mysql -u root -p密码
退出是 exit 或者 Ctrl+c即可
登录的是DBMS
------------------------------------------------分割线-------------------------------------------------------
show databases;//显示有哪些数据库
use mysql;//选用一个数据库
show tables;//看里面有哪些表
desc user; // 查看表的结构
show create table user; // => 查看创建表得sql语句,表得存储引擎以及编码格式
注:假如我们use mysql;选择这个数据库,然后show tables from test;那么我现在其实还是在mysql库里面 只是查看了一下test的表。
// 创建数据库
create database tulun;
// 删除数据库
drop databases tulun;
// 选择数据库
use tulun; // show tables;
//看一下数据库服务器版本号:
select version();
或者用下面的这两个DOS命令:
mysql --version
mysql -V
//看一下 现在我位于哪个数据库
select database();
// 创建一张学生表 id int name varchar age int sex enum score double level “”
// 字段名称+字段类型+字段得完整性约束条件(主键,外键,unique,not null, default, auto_increment)
create table student(id int primary key,
name varchar(20), age tinyint,
sex enum(‘男’, ‘女’), score double,
level varchar(20) default “不合格”);
// 删除表
drop table student;
// insert
insert into student values();
// delete
delete fron student where score < 60.0 or age < 20;
// update
update student set level=“合格” where score > 90.0;
// select 单表得查询和多表得查询
select * from student;
select id,name,score,level front student;
select * from student where score>60.0;
select name,age,sex where level = ‘合格’;
SQL得排序order by 字段名称 asc(默认)/desc 和
分组group by 字段名称 经常和mysql得函数一起使用,得到分组后得详细情况
索引的sql语句 很多学生10000记录 name : zhang san
name字段创建一个索引,mysql server会把表中所有记录的name字段的值进行排序 进行一个二分搜索
create index name_index on student(name);
注意:
1.对区分度高的字段创建索引好;对区分度低的字段不用创建索引了。
2.MySQL Server使用索引的时候,会进行索引优化,如果过滤字段需要搜索表的数据达到60-70%,索引就
被放弃了,执行整表搜索了。
3.如果过滤条件+排序或者分组条件,此时最好创建联合索引
4.对于一张表的一次查询只能用到一个索引
《MySQL索引漫画》
带in的子查询: <=== 为什么多表联合查询时,不建议使用带in子查询,都要写成连接查询,为甚?
select * from
Employeeaddress
where addreddID
in (select AddressID from Employee where EmployeeId=10000)
熟悉单表的CURD,排序和分组,字段创建索引,explain查看SQL执行计划,
连接查询:内连接和外连接查询(左连接和右连接)
select b.country,b.city,b.street
from
Employee a, Employeeaddress b
on a.AddressID = b.addreddID
where a.EmployeeId = 10000;
===> 同样的内连接SQL语句是:
select b.country,b.city,b.street
from
Employee a
inner join
Employeeaddress b
on a.AddressID = b.addreddID
where a.EmployeeId = 10000;
explain: 查看sql语句的执行计划
》》》 了不了解数据库得范式设计???
范式一、范式二、范式三、BC范式、范式四
范式:减少表得冗余,防止数据不一致,提高数据的查询效率;范式越多,表划分的就越多,多表
联合查询的次数就越多,查询的效率就会变慢! 因此范式绝对不是越高越好,一般数据库表的
设计达到范式三就足够了!
student 1000行
id name sex age 选择的课程 课程的总成绩 学生的考试成绩
1 zhang male 20 语文 100 98
------------------------------------------------分割线-------------------------------------------------------
下面是《MYSQL入门很简单的第六章》
一、DQL语言:数据查询语言。主要是针对select操作
二、DML语言:数据操作语言,主要是针对 增删改操作
三、DDL语言:数据定义语言,主要是针对表 库的定义操作
四、TCL语言:事务控制语言,主要是针对 事务和事务的处理
修改表名:
修改字段/属性的属性类型:
上面的错误例子如下:
修改属性名:
表内增加一个新的字段:
表内删除一个字段:(把上面的那个Stest字段删除)
将一个字段放到表的首位去:
将一个字段1放到字段2的后面:
修改表的存储引擎:
以下面为准:
主键可以自增;level 是有默认值的
一条语句,插入多条记录。
把指定字段的一定范围的数据给查询出来:
把年龄大于21的信息都给打印出来:
上图也可以如下:
把年龄在20到21之间的信息查询出来:
把姓司马的狗东西 都查出来:
把名字里面有 炎 的信息查出来:
把名字里面 第二个字是 炎的信息查询出来
把名字为空的信息给打印出来:
下面是 带and的多条件查询:
把姓司马的 而且 还是女的给查出来:
把姓司马的 或者 姓曹的查询出来:
把表中 年龄的去重给打印出来:
SQL得排序order by 字段名称 asc(默认)/desc
分组group by 字段名称 经常和mysql得函数一起使用,得到分组后得详细情况
按照性别分组,然后把姓宋的这个帅气的天才给查出来:
索引的sql语句 很多学生10000记录 name : zhang san
name字段创建一个索引,mysql server会把表中所有记录的name字段的值进行排序 进行一个二分搜索
create index name_index on student(name);
注意:
1.对区分度高的字段创建索引好;对区分度低的字段不用创建索引了。
2.MySQL Server使用索引的时候,会进行索引优化,如果过滤字段需要搜索表的数据达到60-70%,索引就
被放弃了,执行整表搜索了。
3.如果过滤条件+排序或者分组条件,此时最好创建联合索引
4.对于一张表的一次查询只能用到一个索引
建立姓名name索引:
建议姓名索引后的情形:只用查询一行
------------------------------------------------分割线-------------------------------------------------------
下面是建立 level索引的情形:
上图显示:有索引,可是MySQL并没有用。
------------------------------------------------分割线-------------------------------------------------------
建立 score索引:
------------------------------------------------分割线-------------------------------------------------------
如果过滤条件+排序或者分组条件,此时最好创建联合索引
对于一张表的一次查询只能用到一个索引。这里虽然 score 和 name都有索引,但只能用 score_index
过滤条件是 score;score是排序条件。要建立联合索引,首先撤除两个索引:
删除两个索引成功:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
下面是多表查询的操作:
成绩表:为学生学号、课程号、成绩
现在要对这两个表要进行联合查询:(通过相同字段SID)
左连接:left join
右链接 :right join
内连接: inner join
看一下左连接:
分析如上:学生表在左,成绩表在右。返回的是左边表的所有数据以及右边表的(通过相同字段连接起来的)相同的数据。因此左边存在 而右边不存在的则全部就成了 NULL。
看一下右链接:
分析如上:学生表在左,成绩表在右。返回的是右边表的所有数据以及左边表的(通过相同字段连接起来的)相同的数据。
看一下内连接:
分析如上:学生表通过内连接来连接成绩表。也是学生表在左,成绩表在右。返回的是左右两表都同时存在的数据(通过相同字段连接起来的)。(内连接是连个表同时存在的数据)
例子如下:
《MySQL索引漫画》
使用索引时,有以下一些技巧和注意事项:
(1)越小的数据类型通常更好:越小的数据类型通常在磁盘、内存和CPU缓存中都需要更少的空间,处理起来更快。
(2)简单的数据类型更好:整型数据比起字符,处理开销更小,因为字符串的比较更复杂。在MySQL中,应该用内置的日期和时间数据类型,而不是用字符串来存储时间;以及用整型数据类型存储IP地址。
(3)尽量避免NULL:应该指定列为NOT NULL,除非你想存储NULL。在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值。
(4)索引不会包含有NULL值的列。
但是如果是同样的sql如果在之前能够使用到索引,那么现在使用不到索引,以下几种主要情况:
随着表的增长,where条件出来的数据太多,大于15%,使得索引失效(会导致CBO计算走索引花费大于走全表)
统计信息失效 需要重新搜集统计信息
索引本身失效 需要重建索引
下面是一些不会使用到索引的原因
索引失效
13)如果MySQL估计使用索引比全表扫描更慢,则不使用索引。例如如果列key_part1均匀分布在1到100之间,查询时使用索引就不是很好
mysql>select * from table_name where key_part1>1 and key_part<90;
14)如果使用MEMORY/HEAP表并且where条件中不使用“=”进行索引列,那么不会用到索引。Heap表只有在“=”的条件下会使用索引。因为用的是哈希索引。
15)用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。
表见mysql索引之五:组合索引怎么应该怎么选取引导列
mysql> show index from test1\G;
*************************** 1. row ***************************
Table: test1
Non_unique: 1
Key_name: inx_id_name
Seq_in_index: 1
Column_name: name
Collation: A
Cardinality: 552589
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
*************************** 2. row ***************************
Table: test1
Non_unique: 1
Key_name: inx_id_name
Seq_in_index: 2
Column_name: id
Collation: A
Cardinality: 567855
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
rows in set (0.00 sec)
ERROR:
No query specified
mysql>
从上面可以发现只有name和id列上面有索引。来看如下的执行计划。
mysql> explain extended select * from test1 where name='name100' or dept='dept100';
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | test1 | NULL | ALL | inx_id_name | NULL | NULL | NULL | 769014 | 19.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
row in set, 2 warnings (0.00 sec)
mysql>
16)如果将要使用的索引列不是复合索引列表中的第一部分,则不会使用索引
如下例子:可见虽然在id上面建有复合索引,但是由于id不是索引的第一列,那么在查询中这个索引也不会被MySQL采用。
mysql> explain select * from test1 where id=1;
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | test1 | NULL | ALL | NULL | NULL | NULL | NULL | 787947 | 10.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+----------+-------------+
row in set, 1 warning (0.00 sec)
mysql>
17)如果like是以%开始,可见虽然在name上面建有索引,但是由于where 条件中like的值的“%”在第一位了,那么MySQL也会采用这个索引。
如果WHERE子句的查询条件里使用了比较操作符LIKE和REGEXP,MYSQL只有在搜索模板的第一个字符不是通配符的情况下才能使用索引。比如说,如果查询条件是LIKE ‘abc%’,MYSQL将使用索引;如果条件是LIKE ‘%abc’,MYSQL将不使用索引。
18)独立的列(对列变量需要计算(聚合运算、类型转换等))
独立的列是指索引列不能是表达式的一部分,也不是是函数的参数。例如以下两个查询无法使用索引:
1)表达式: select actor_id from sakila.actor where actor_id+1=5;
2)函数参数:select … where TO_DAYS(CURRENT_DATE) - TO_DAYS(date_col)<=10;应该把列计算转换成常量计算。
示例:
如果列类型是字符串,但在查询时把一个数值型常量赋值给了一个字符型的列名name,那么虽然在name列上有索引,但是也没有用到。
mysql> explain select * from company2 where name=294\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: company2
type: ALL
possible_keys: ind_company2_name
key: NULL
key_len: NULL
ref: NULL
rows: 1000
Extra: Using where
row in set (0.00 sec)
而下面的sql语句就可以正确使用索引。
mysql> explain select * from company2 where name name=‘294'\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: company2
type: ref
possible_keys: ind_company2_name
key: ind_company2_name
key_len: 23
ref: const
rows: 1
Extra: Using where
row in set (0.00 sec)
19).在JOIN操作中(需要从多个数据表提取数据时),MYSQL只有在主键和外键的数据类型相同时才能使用索引,否则即使建立了 索引也不会使用
20).在ORDER BY操作中,MYSQL只有在排序条件不是一个查询条件表达式的情况下才使用索引。尽管如此,在涉及多个数据表的查询里,即使有索引可用,那些索引在加快ORDER BY操作方面也没什么作用。
21).不要给“性别”增加索引。如果某个数据列里包含着许多重复的值,就算为它建立了索引也不会有很好的效果。比如说,如果某个数据列里包含了净是些诸如“0/1”或“Y/N”等值,就没有必要为它创建一个索引。
简单的说吧,不需要,因为性别,就两个值男与女(人妖不算,呵)。为这两个值建立索引是不值得的,因为无论多少条记录,建立性别的索引,最多让你的语句少检索一半。但与建立索引带来的损失比,捡芝麻丢西瓜。(可能不准确,但大意如些)。
打个比方,数据库就好比一本新华字典,我们查数据时,可以根据拼音来查,字在字典的排序是根据拼音来排序的,我们要查一个字,可以根据拼音很快就能查到我们要查的字,这就叫作聚集索引!换句话说,聚集索引就是按照物理排序的,也因为是按物理排序的,所以一张表只能有一个聚集索引,也是最快的索引。当然,我们也可以根据部首来查,但是这种查询必须先查找到部首,然后再到检索表查到那么字,最后才能查到我们需要的字,你没办法像拼音查法一样翻翻字典就可以查到,这就叫作普通索引。普通索引可以有多个。
假如一本字典里全是"男"和"女"两个字,那么在检索表里也有很多个"男"和"女",这对查询帮助不大。
22).如果对大的文本进行搜索,使用全文索引而不使用like“%…%”.
23).如果列名是索引,使用column_name is null将使用索引。
如下
mysql> explain select * from company2 where name is null\G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: company2
type: ref
possible_keys: ind_company2_name
key: ind_company2_name
key_len: 11
ref: const
rows: 1
Extra: Using where
row in set (0.00 sec)
24).不使用NOT IN和<>操作
NOT IN和<>操作都不会使用索引将进行全表扫描。NOT IN可以NOT EXISTS代替,id<>3则可使用id>3 or id<3来代替。
25).排序的索引问题
mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。
26).使用短索引
对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。
27).索引不会包含有NULL值的列
只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。
28).使用ENUM而不是字符串
ENUM保存的是TINYINT,别在枚举中搞一些“中国”“北京”“技术部”这样的字符串,字符串空间又大,效率又低。
以上第三部分 来自于博客:
https://www.cnblogs.com/duanxz/p/5244703.html