mysql学习记录

初级部分

安装---计算机上的服务需要启动

什么是存储引擎?

数据库存储引擎是数据库底层软件组件,数据库管理系统使用数据引擎进行创建、查询、更新和删除数据操作。不
同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎还可以获得特定的功能。
MySQL 的核心就是存储引擎。提示:InnoDB 事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定
和外键。MySQL 5.5.5 之后,InnoDB 作为默认存储引擎。

如何选择 MySQL 存储引擎

不同的存储引擎都有各自的特点,以适应不同的需求,如表所示。为了做出选择,首先要考虑每一个存储引擎提供了哪些不同的功能。
 

功能MylSAMMEMORYInnoDBArchive
存储限制256TBRAM64TBNone
支持事务NoNoYesNo
支持全文索引YesNoNoNo
支持树索引YesYesYesNo
支持哈希索引NoYesNoNo
支持数据缓存NoN/AYesNo
支持外键NoNoYesNo


可以根据以下的原则来选择 MySQL 存储引擎:

  • 如果要提供提交、回滚和恢复的事务安全(ACID 兼容)能力,并要求实现并发控制,InnoDB 是一个很好的选择。
  • 如果数据表主要用来插入和查询记录,则 MyISAM 引擎提供较高的处理效率。
  • 如果只是临时存放数据,数据量不大,并且不需要较高的数据安全性,可以选择将数据保存在内存的 MEMORY 引擎中,MySQL 中使用该引擎作为临时表,存放查询的中间结果。
  • 如果只有 INSERT 和 SELECT 操作,可以选择Archive 引擎,Archive 存储引擎支持高并发的插入操作,但是本身并不是事务安全的。Archive 存储引擎非常适合存储归档数据,如记录日志信息可以使用 Archive 引擎。
记录:
 WHERE NAME IS NOT NULL---》mysql中判断字段非空
delete 支持事务回滚,truncate 不支持事务回滚
limit 用法
SELECT * FROM dept LIMIT 1; //第一个开始,默认选取一个
SELECT * FROM dept LIMIT 1,2; //从第二个开始 ,选取两个.

可以与group by 联合使用选取最大,最小值

select 语句

1用distinct关键字, 如果结果中有完全相同的行,就去除重复行 

SELECT DISTINCT alogin FROM account

2起别名 用as,可省略as

SELECT id xx FROM account 

3加号的作用:仅仅只有一个作用运算符

SELECT 100+90 结果100--》两个都为数值类型作加法运算

SELECT 'a'+90  结果90--》其中有字符型,将字符型转换为数值型,成功,做加法,失败,字符型的值为0

SELECT 'a'+90  结果90  SELECT null+90  结果null

mysql查询

条件查询 where 

between ...and ....在....之间 

not....between ...and ... 不在之间

mysql 函数

select 函数名(实参列表)【from 表】--实参列表用到

1字符函数

UPPER(s)将字符串转换为大写
TRIM(s)去掉字符串 s 开始和结尾处的空格

2数字函数

ABS(x)返回 x 的绝对值 
CEIL(x)返回大于或等于 x 的最小整数 
FLOOR(x)返回小于或等于 x 的最大整数  
COUNT(expression)返回查询的记录总数,expression 参数是一个字段或者 * 号

SELECT ROUND(1.23456,3) -->保留三位小数,四舍五入 

3日期函数

now() -->select now()-->返回当前日期和时间

CURTIME()    返回当前时间,不包含日期

CURDATE()返回当前日期,不包含时间

 YEAR(d) 返回年  -->select year(now())

str_to_date(str, format) 函数  --》日期格式字符串转化为指定格式的日期

date_format(date, format) 函数--》日期转为字符串

%m 两位数字表示月份(01,02, ...,12)
%c 数字表示月份(1,2, ...,12) 
%Y 四位数字表示的年份(2015,2016...)
%y 

 两位数字表示的年份(15,16...)

%d 两位数字表示月中天数(01,02, ...,31)
%S、%s两位数字形式的秒( 00,01, ..., 59)
%I、%i两位数字形式的分( 00,01, ..., 59)
小时 %H24小时制,两位数形式小时(00,01, ...,23)
%h12小时制,两位数形式小时(00,01, ...,12)

 SELECT STR_TO_DATE('1998-1-2', '%Y-%m-%d')//字符串转为日期

SELECT DATE_FORMAT(NOW(), '%Y-%m-%d'); //时间转字符串

其他函数:

SELECT USER()--》当前用户
SELECT VERSION()--》版本号

SELECT ISNULL(NULL)--》值为1,否则SELECT ISNULL(‘a’)-->值为0

IFNULL(v1,v2)如果 v1 的值不为 NULL,则返回 v1,否则返回 v2。
IF(expr,v1,v2)如果表达式 expr 成立,返回结果 v1;否则,返回结果 v2。

 CASE:函数

常见的分组函数:
    sum(字段):求该字段的所有值的和
    avg(字段):求该字段的平均值
    max(字段):求最大值
    min(字段):求最小值
    count(字段):计算该字段中的非空值的个数

sum和avg只支持数值型做参数max、min、count可以支持任意类型做参数,分组函数都忽略null,可以和distinct 使用--》select sum(distinct  salary) from emp;

分组函数对应分组查询:

语法:select 分组函数,column from table [where condition] [group by ] column  having 条件

列必须出现在group by的后面

比如-->查询每个部门的平均工资--》select sum(salary),dept_id from dept group by dept_id.(相当于只有个不同的部门存活)

1.多个字段分组,比如按照部门,和工资分组--》group by dept_id,salary; -->用逗号隔开。

2group by 后面支持函数---如按照名字长度分组 group by length(name);

3 支持排序 group by length(name) order by datetime---放在group by的后面

多表查询

多个表查询会用到连接条件,如果没有有效的连接条件,就会用其中一张表的数据,区另一张表区匹配所有。

如果第一个表有m行,第二个表n行,就会查出m*n,-----》这是错的。解决办法----添加有效的连接条件。

1等值连接:连接条件用"=" 表示 如:where a.id=b.id;

SELECT * FROM tbl_dept a ,tbl_emp b WHERE a.id = b.deptId;

2内连接 SELECT * FROM tbl_dept a INNER JOIN tbl_emp b ON a.id = b.deptId;

3非等值连接 where 后面条件已经不用等号了

4自连接:一张表自己连接自己--需要一张表查询两边以上,例如,查出一个员工的名字,和他上级的名字

可以先查出员工的名字和他上级的编号,再根据上级的编号进行查询-

select e.name,e.id,m.name,m.id from emp e,emp m where e.id=m.id;

内连接类似等值连接

外连接(左外和右外)

左外连接--左边的主表

右外连接--右边的是主表

交叉连接--就是笛卡尔积 cross

全外连接--full---目前不支持

子查询

子查询---出现在其他语句的select,称为子查询--不仅仅的出现在查询语句中。


1、where型子查询:把内层查询的结果作为外层查询的比较条件
2、from型子查询:把内层的查询结果当成临时表,供外层sql再次查询。查询结果集可以当成表看待。临时表要
使用一个别名。
3.exists型子查询:把外层sql的结果,拿到内层sql去测试,如果内层的sql成立,则该行取出。内层查询是
exists后的查询。也叫相关子查询,可以用in代替
4. any, in ,all子查询
5.select 支持标量,from 表子查询

标量子查询,单行子查询---结果集只有一行一列--where having后面,> < >= <= =
列子查询---结果集只有一列多行  in,any,all
行子查询---结果集一行多列---就是结果集是一个表的一行多个字符段
表子查询----多行多列

子查询优先于主查询,子查询结果集只能是一行一列

------------
SELECT * FROM USER WHERE NAME =(
SELECT MAX(NAME) FROM USER);// 分组函数查询返回的字段默认就是原字段

联合查询 union---将查询语句的多个结果合并成一个结果集--查询两张表没有关系

SELECT * FROM USER WHERE NAME='qqq' AND addr='ccc'

SELECT * FROM USER WHERE NAME='qqq' UNION SELECT * FROM USER WHERE addr='ccc';

注意:使用时多个表的字段一致,顺序相同。使用union 去重,不想去重在union后面加上all,则是union all

dml 数据操作语言--插入,修改,删除。

insert into table values(1,‘xx’),(2,'xde');//支持插入多行

修改 update table set 列=值,列=值 where condition.

--->可以修改多表:update table1 inner join table on 连接条件 set 列=值,,,,

删除delete from table where condition

ddl 数据库定义语言

create database 库名---创建数据库

user database 使用数据库

drop database if exists 库名

表的创建 

表的修改:

修改列名,

ALTER TABLE USER CHANGE COLUMN  addr addx INT;// 修改列名的时候可以修改类型,COLUMN  可以省略

修改类型和约束,

ALTER TABLE USER MODIFY COLUMN addx VARCHAR(32)

添加列,

ALTER TABLE USER ADD COLUMN sal DOUBLE ;

删除列,

ALTER TABLE USER DROP COLUMN sal ;

修改表名

ALTER TABLE USER RENAME TO new_table_name

-------------总结 ALTER TABLE table_name drop |add| modify| change column 列名 类型---------

表的删除 drop table table_name

表的复制 :

CREATE TABLE userxc LIKE userxx //复制表的结构--没有数据

CREATE TABLE userd1 SELECT * FROM userxc  //复制表的结构,有数据。后面的查询语句就是查询出结构和数据

mysql 中数据类型:

1数值类型:整形,浮点

TINYINT、MEDIUMINT和BIGINT。一样的,区别就是范围大小不一样。

创建无符号类型字段 使用UNSIGNED 关键字,默认有符号值,如果插入的数据超出范围,会包out of range 异常,并插入临界值。不设置长度,会有默认长度,如int(11),这个11不是指类型的范围,而是数值显示的长度,使用时候需要zerofill 搭配,并且不支持有符号数(默认没有负数)

CREATE TABLE des(
id INT UNSIGNED
)
INSERT INTO des VALUE(-1) #可以插入,但是结果为0。

浮点型 float 4个字节 double 八个字节

DECIMAL(m,d) 定点型 m--小数部分+整数部分,d小数部分 。如DECIMAL(5,2)最大值999,99 ,如果插入的数据超出范围,就用临界值代替。m,d 都可以省略 ,float,double一般无所谓,decimal 默认为(10,0)。--使用decimal 需要精度比较高。

demo:
CREATE TABLE des1(
age DOUBLE(5,2),
age1 FLOAT(5,2),
age2 DECIMAL(5,2)
)

选择的类型越简单越好,保存的数值越小越好。

字符串类型 较短的文本char,varchar,  长文本 text,blob

日期和时间类型

DATETIME    混合日期和时间值

TIMESTAMP   混合日期和时间值,时间戳--受到时区影响。

DATE 只保存日期

time 保存时间

year 保存年份

什么是约束?

约束实际上就是表中数据的限制条件
非空约束(not null)
唯一性约束(unique)
主键约束(primary key) PK
外键约束(foreign key) FK
default 设置默认值
检查约束(目前MySQL不支持、Oracle支持)

demo:列级约束

CREATE TABLE a(
id int PRIMARY KEY,
NAME char(11) NOT NULL,
did int UNIQUE,
age int  INT DEFAULT 18
)

表级约束可以给约束起名字
demo:
CREATE TABLE a(
id int,
NAME char(11),
did int,
age int,
constraint pk_name primary key(id),
constraint uk_name unique(did)
)

主键外键,唯一键自动生成索引。show index from table_name;

主键和unique
1都可以保证唯一
2主键不能为空,unique 可以为空
3一个表只有一个主键,unique可以多个。
4都可以组合

修改表时候添加约束:

1添加非空约束

alter table tb_name modify column stuname varchar(32) not null

2添加默认约束

alter table tb_name modify column stuage default 18

3添加主键约束

列级约束:alter table tb_name modify column id primary key

表级约束:alter table tb_name  add CONSTRAINT pk  primary key(id)

4唯一约束

alter table tb_name modify column studid int unique;

删除唯一约束

alter table tb_name drop index (unique_name)

事务tcl

BEGIN 开始一个事务
ROLLBACK 事务回滚
COMMIT 事务确认

脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据。

不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。(多次读取的数据不一致)

幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

脏读和幻读类似,脏读针对更新,幻读一般针对插入和删除。

MySQL事务隔离级别---默认:默认的事务隔离级别为repeatable-read,最低的隔离级别为读未提交

事务隔离级别脏读不可重复读幻读
读未提交(read-uncommitted)
不可重复读(read-committed)
可重复读(repeatable-read)
串行化(serializable)

查看事务的隔离级别:select @@tx_isolation;

set session transaction isolation level read uncommitted; // 设置隔离级别

start transaction;//开启事务

脏读,读第一个事务修改了,第二个事务就可以看到了修改后的信息,但是第一个事务回滚了,第二个事务的数据又开始不一致了。

不可重复读,第一个事务修改了,第二个事务看不到,第一个事务提交了,第二个事务看到了,两次结果不一样。

幻读,针对插入,比如查看数据是两个,但是另一个事物插入一条数据,当前事务,修改数据了之后竟然是三条数据收到影响。

只有串行化才能解决数据并发问题.

set autocommit=0,
当前session禁用自动提交事物,自此句执行以后,每个SQL语句或者语句块所在的事务都需要显示"commit"才能提交事务。

savepoint 保存点,搭配rollback 

BEGIN TRANSACTION;
INSERT INTO dept(dbname,db_nu) VALUES('5','aa');;
SAVEPOINT a;
INSERT INTO dept(dbname,db_nu) VALUES('ac','csa');
ROLLBACK TO a;

视图:

CREATE VIEW myview AS SELECT dbname FROM dept; //创建视图

CREATE OR REPLACE VIEW myview AS SELECT dbname FROM dept;//修改视图--》alter view myview as ...

删除视图

drop view 视图名,视图名

查看视图 desc 视图名

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

高级

mysql --关系型数据库

1索引优化

创建索引

CREATE INDEX idx_dept_name ON dept(dbname)//单值索引

CREATE INDEX idx_dept_name_nu ON dept(dbname,db_nu)//多值索引

MySQL官方对索引的定义为:索引(Index)是帮助MySQL高校获取数据的数据结构。
可以得到索引的本质:索引是数据结构。

myi 文件存放表索引

数据本身之外,数据库还维护着一个满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,

这样就可以在这些数据结构的基础上实现高级查找算法,这种数据结构就是索引。


优势:

1类似大学图书馆建书目索引,提高数据检索效率,降低数据库的IO成本

2通过索引列对数据进行排序,降低数据排序成本,降低了CPU的消耗

劣势
1虽然索引大大提高了查询速度,同时却会降低更新表的速度,如果对表INSERT,UPDATE和DELETE。
因为更新表时,MySQL不仅要不存数据,还要保存一下索引文件每次更新添加了索引列的字段,
都会调整因为更新所带来的键值变化后的索引信息

2索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要花时间研究建立优秀的索引,或优化查询语句

创建index

1CREATE [UNIQUE] INDEX  indexName ON mytable(columnname(length));

CREATE  INDEX  xx ON utest (NAME);

2ALTER TABLE mytable ADD [UNIQUE]  INDEX [indexName] (columnname(length));
ALTER TABLE utest2 ADD  INDEX  xs(xc);

删除index

drop index index_name on table_name ;
查看index
SHOW INDEX FROM dept

哪些情况需要创建索引:
1.主键自动建立唯一索引
2.频繁作为查询的条件的字段应该创建索引
3.查询中与其他表关联的字段,外键关系建立索引
4.频繁更新的字段不适合创建索引

哪些情况不要创建索引:
1.表记录太少
2.经常增删改的表
3.数据重复且分布平均的表字段,因此应该只为经常查询和经常排序的数据列建立索引。
注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。
性能分析: MySQL常见瓶颈-----》
1 CPU:CPU在饱和的时候一般发生在数据装入在内存或从磁盘上读取数据时候
2 IO:磁盘I/O瓶颈发生在装入数据远大于内存容量时
3 服务器硬件的性能瓶颈:top,free,iostat和vmstat来查看系统的性能状态

explain
是什么(查看执行计划)
(如何用)explain+sql语句

EXPLAIN SELECT * FROM dept;

查看type 类型---如果为all,则进行索引优化
如果key = null,则索引没建立,建立没用,就是索引失效
possible_key  理论上用到的key


extra 包含不适合在其他列中显示但十分重要的额外信息

    

单表,在查询的条件字段上或者字段上加上index
两表, 左连接,在右表的字段上加index,右连接--同样左表加index,没建立index,type是all
三表,会使用join 缓存,没建立index,type是all,也是在右边的两张表上建立查询字段的index
结论:
1 尽量减少join语句的中的循环总次数,用小的结果集驱动大结果集,比如书的种类驱动书。
2 尽量优先优化内存循环
3 保证join 索引

索引失效 

索引失效--》建立索引,没用上

1.最佳左前缀法则--》如果索引了多例,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。
2.不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描
3.尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select*
4.mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描
5.is null,is not null 也无法使用索引
6.少用or,用它连接时会索引失效
7.字符串不加单引号索引失效   select * from user where name=100,index失效,但是能查出,mysql底层
做了类型装换,将数值型转为varchar类型。

8.少用or,用它连接时会索引失效
9.存储引擎不能使用索引中范围条件右边的列
10.like以通配符开头('$abc...')mysql索引失效会变成全表扫描操作;-->百分号最好卸载最右边

问题:解决like'%字符串%'索引不被使用的方法??---使用覆盖索引解决!
题目:为字段分别建立1,2,3,4索引
1 查询顺序颠倒,索引精度不变
2 3>‘3’ 范围之后全失效,用了两个
3 4>4 and 3=3 mysql底层会优化,然后用到了四个,4后面用不到了
4 order by 3 ,3的作用排序 和四关系没了
5 1=1 2=2 order by 4 没有4 ,会出现 mysql内部排序 
6 1=1 order by 3,2 排序的时候最好出现按照索引建立的顺序 mysql内部排序 ,有个特例,如下
7 1=1 ,2=2order by 3,2 ,排序字段是个常量
8 1=1 2=2 group by 4,3   Using temporary 临时表

建议: 

在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。

在选择组合索引的时候,尽量选择可以能包含当前query中的where子句中更多字段的索引

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值