MYSQL进阶,新手变司机
一、视图
视图是一个虚拟表(非真实存在),其本质是【根据SQL语句获取动态的数据集,并为其命名】,用户使用时只需使用【名称】即可获取结果集,并可以将其当作表来使用。
- SELECT
- *
- FROM
- (
- SELECT
- nid,
- NAME
- FROM
- tb1
- WHERE
- nid > 2
- ) AS A
- WHERE
- A. NAME > 'alex';
临时表搜索
1、创建视图
- --格式:CREATE VIEW 视图名称 AS SQL语句
- CREATE VIEW v1 AS
- SELET nid,
- name
- FROM
- A
- WHERE
- nid > 4
2、删除视图
- --格式:DROP VIEW 视图名称
- DROP VIEW v1
3、修改视图
- -- 格式:ALTER VIEW 视图名称 AS SQL语句
- ALTER VIEW v1 AS
- SELET A.nid,
- B. NAME
- FROM
- A
- LEFT JOIN B ON A.id = B.nid
- LEFT JOIN C ON A.id = C.nid
- WHERE
- A.id > 2
- AND C.nid < 5
4、使用视图
- select * from v1
二、触发器
对某个表进行【增/删/改】操作的前后如果希望触发某个特定的行为时,可以使用触发器,触发器用于定制用户对表的行进行【增/删/改】前后的行为。
1、创建基本语法
- # 插入前
- CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
- BEGIN
- ...
- END
- # 插入后
- CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
- BEGIN
- ...
- END
- # 删除前
- CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW
- BEGIN
- ...
- END
- # 删除后
- CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW
- BEGIN
- ...
- END
- # 更新前
- CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW
- BEGIN
- ...
- END
- # 更新后
- CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW
- BEGIN
- ...
- END
- delimiter //
- CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
- BEGIN
- IF NEW. NAME == 'alex' THEN
- INSERT INTO tb2 (NAME)
- VALUES
- ('aa')
- END
- END//
- delimiter ;
插入前触发器
- delimiter //
- CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
- BEGIN
- IF NEW. num = 666 THEN
- INSERT INTO tb2 (NAME)
- VALUES
- (''),
- ('') ;
- ELSEIF NEW. num = 555 THEN
- INSERT INTO tb2 (NAME)
- VALUES
- (''),
- ('') ;
- END IF;
- END//
- delimiter ;
后触发器
特别的:NEW表示即将插入的数据行,OLD表示即将删除的数据行。
2、删除触发器
- DROP TRIGGER tri_after_insert_tb1;
3、使用触发器
触发器无法由用户直接调用,而是由于对表的【增/删/改】操作被动引发的。
- insert into tb1(num) values(666)
三、存储过程
存储过程是一个SQL语句集合,当主动去调用存储过程时,其中内部的SQL语句会按照逻辑执行。
1、创建存储过程
- -- 创建存储过程
- delimiter //
- create procedure p1()
- BEGIN
- select * from t1;
- END//
- delimiter ;
- -- 执行存储过程
- call p1()
对于存储过程,可以接收参数,其参数有三类:
- in 仅用于传入参数用
- out 仅用于返回值用
- inout 既可以传入又可以当作返回值
- -- 创建存储过程
- delimiter \\
- create procedure p1(
- in i1 int,
- in i2 int,
- inout i3 int,
- out r1 int
- )
- BEGIN
- DECLARE temp1 int;
- DECLARE temp2 int default 0;
- set temp1 = 1;
- set r1 = i1 + i2 + temp1 + temp2;
- set i3 = i3 + 100;
- end\\
- delimiter ;
- -- 执行存储过程
- set @t1 =4;
- set @t2 = 0;
- CALL p1 (1, 2 ,@t1, @t2);
- SELECT @t1,@t2;
有参存储过程
2、删除存储过程
- drop procedure proc_name;
3、执行存储过程
- -- 无参数
- call proc_name()
- -- 有参数,全in
- call proc_name(1,2)
- -- 有参数,有in,out,inout
- set @t1=0;
- set @t2=3;
- call proc_name(1,2,@t1,@t2)
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- import pymysql
- conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='t1')
- cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
- # 执行存储过程
- cursor.callproc('p1', args=(1, 22, 3, 4))
- # 获取执行完存储的参数
- cursor.execute("select @_p1_0,@_p1_1,@_p1_2,@_p1_3")
- result = cursor.fetchall()
- conn.commit()
- cursor.close()
- conn.close()
- print(result)
pysql执行存储过程
四、事务
事务用于将某些操作的多个SQL作为原子性操作,一旦有某一个出现错误,即可回滚到原来的状态,从而保证数据库数据完整性。
- delimiter \\
- create PROCEDURE p1(
- OUT p_return_code tinyint
- )
- BEGIN
- DECLARE exit handler for sqlexception
- BEGIN
- -- ERROR
- set p_return_code = 1;
- rollback;
- END;
- DECLARE exit handler for sqlwarning
- BEGIN
- -- WARNING
- set p_return_code = 2;
- rollback;
- END;
- START TRANSACTION;
- DELETE from tb1;
- insert into tb2(name)values('seven');
- COMMIT;
- -- SUCCESS
- set p_return_code = 0;
- END\\
- delimiter ;
- set @i =0;
- call p1(@i);
- select @i;
支持事务的存储过程
五、索引
索引,是数据库中专门用于帮助用户快速查询数据的一种数据结构。类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获取即可。
- 30
- 10 40
- 5 15 35 66
- 1 6 11 19 21 39 55 100
MySQL中常见索引有:
- 普通索引
- 唯一索引
- 主键索引
- 组合索引
1、普通索引
普通索引仅有一个功能:加速查询
- create table in1(
- nid int not null auto_increment primary key,
- name varchar(32) not null,
- email varchar(64) not null,
- extra text,
- index ix_name (name)
- )
创建表和索引
- create index index_name on table_name(column_name)
创建索引
- drop index_name on table_name;
删除索引
- show index from table_name;
查看索引
注意:对于创建索引时如果是BLOB 和 TEXT 类型,必须指定length。
- create index ix_extra on in1(extra(32));
2、唯一索引
唯一索引有两个功能:加速查询 和 唯一约束(可含null)
- create table in1(
- nid int not null auto_increment primary key,
- name varchar(32) not null,
- email varchar(64) not null,
- extra text,
- unique ix_name (name)
表+唯一索引
- create unique index 索引名 on 表名(列名)
创建唯一索引
- drop unique index 索引名 on 表名
删除唯一索引
3、主键索引
主键有两个功能:加速查询 和 唯一约束(不可含null)
- create table in1(
- nid int not null auto_increment primary key,
- name varchar(32) not null,
- email varchar(64) not null,
- extra text,
- index ix_name (name)
- )
- OR
- create table in1(
- nid int not null auto_increment,
- name varchar(32) not null,
- email varchar(64) not null,
- extra text,
- primary key(ni1),
- index ix_name (name)
- )
创建主键和主键索引
- alter table 表名 add primary key(列名);
创建主键
- alter table 表名 drop primary key;
- alter table 表名 modify 列名 int, drop primary key;
删除主键
4、组合索引
组合索引是将n个列组合成一个索引
其应用场景为:频繁的同时使用n列来进行查询,如:where n1 = 'alex' and n2 = 666。
- create table in3(
- nid int not null auto_increment primary key,
- name varchar(32) not null,
- email varchar(64) not null,
- extra text
- )
创建表
- create index ix_name_email on in3(name,email);
创建组合索引
如上创建组合索引之后,查询:
- name and email -- 使用索引
- name -- 使用索引
- email -- 不使用索引
注意:对于同时搜索n个条件时,组合索引的性能好于多个单一索引合并。
5、索引的相关命令和注意事项
- # 查看索引
- show index from 表名
- # 查看执行时间
- set profiling = 1; # 开启profiling
- SQL... # 执行SQL语句
- show profiles; # 查看结果
- # 避免使用select *
- # count(1)或count(列) 代替 count(*)
- # 创建表时尽量时 char 代替 varchar
- # 表的字段顺序固定长度的字段优先
- # 组合索引代替多个单列索引(经常使用多个条件查询时)
- # 尽量使用短索引
- # 使用连接(JOIN)来代替子查询(Sub-Queries)
- # 连表时注意条件类型需一致
- # 索引散列值(重复少)不适合建索引,例:性别不适合
6、正确使用索引
- # like '%xx',避免%_写在开头
- select * from tb1 where name like '%n';
- # 使用函数
- select * from tb1 where reverse(name) = 'nick';
- # or
- select * from tb1 where nid = 1 or email = '630571017@qq.com';
- 注:当or条件中有未建立索引的列才失效,否则会走索引
- # 类型不一致
- 如果列是字符串类型,传入条件是必须用引号引起来。
- select * from tb1 where name = 999;
- # !=,不等于
- select * from tb1 where name != 'nick'
- 注:如果是主键,则还是会走索引
- select * from tb1 where nid != 123
- # >,大于
- select * from tb1 where name > 'nick'
- 注:如果是主键或索引是整数类型,则还是会走索引
- select * from tb1 where nid > 123
- select * from tb1 where num > 123
- # order by
- select email from tb1 order by name desc;
- 当根据索引排序时候,选择的映射如果不是索引,则不走索引
- 注:如果对主键排序,则还是走索引:
- select * from tb1 order by nid desc;
- # 组合索引最左前缀
- 如果组合索引为:(name,email),查询使用:
- name and email -- 使用索引
- name -- 使用索引
- email -- 不使用索引
六、其他
- delimiter \\
- CREATE PROCEDURE proc_if ()
- BEGIN
- declare i int default 0;
- if i = 1 THEN
- SELECT 1;
- ELSEIF i = 2 THEN
- SELECT 2;
- ELSE
- SELECT 7;
- END IF;
- END\\
- delimiter ;
if语句
- delimiter \\
- CREATE PROCEDURE proc_while ()
- BEGIN
- DECLARE num INT ;
- SET num = 0 ;
- WHILE num < 10 DO
- SELECT
- num ;
- SET num = num + 1 ;
- END WHILE ;
- END\\
- delimiter ;
while循环
- delimiter \\
- CREATE PROCEDURE proc_repeat ()
- BEGIN
- DECLARE i INT ;
- SET i = 0 ;
- repeat
- select i;
- set i = i + 1;
- until i >= 5
- end repeat;
- END\\
- delimiter ;
repeat循环
- delimiter \\
- CREATE PROCEDURE proc_loop ()
- BEGIN
- declare i int default 0;
- loop_label: loop
- select i;
- set i=i+1;
- if i>=5 then
- leave loop_label;
- end if;
- end loop;
- END\\
- delimiter ;
loop
- delimiter \\
- DROP PROCEDURE IF EXISTS proc_sql \\
- CREATE PROCEDURE proc_sql ()
- BEGIN
- declare p1 int;
- set p1 = 11;
- set @p1 = p1;
- PREPARE prod FROM 'select * from tb2 where nid > ?';
- EXECUTE prod USING @p1;
- DEALLOCATE prepare prod;
- END\\
- delimiter ;
动态执行mysql
七、执行计划
- mysql> explain select * from suoning;
- +----+-------------+---------+------+---------------+------+---------+------+------+-------+
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
- +----+-------------+---------+------+---------------+------+---------+------+------+-------+
- | 1 | SIMPLE | suoning | ALL | NULL | NULL | NULL | NULL | 4 | |
- +----+-------------+---------+------+---------------+------+---------+------+------+-------+
- 1 row in set (1.67 sec)
- id
- 查询顺序标识
- 如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;
- +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
- | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
- +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
- | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 9 | NULL |
- | 2 | DERIVED | tb1 | range | PRIMARY | PRIMARY | 8 | NULL | 9 | Using where |
- +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
- 特别的:如果使用union连接气值可能为null
- select_type
- 查询类型
- SIMPLE 简单查询
- PRIMARY 最外层查询
- SUBQUERY 映射为子查询
- DERIVED 子查询
- UNION 联合
- UNION RESULT 使用联合的结果
- ...
- table
- 正在访问的表名
- type
- 查询时的访问方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
- ALL 全表扫描,对于数据表从头到尾找一遍
- select * from tb1;
- 特别的:如果有limit限制,则找到之后就不在继续向下扫描
- select * from tb1 where email = 'seven@live.com'
- select * from tb1 where email = 'seven@live.com' limit 1;
- 虽然上述两个语句都会进行全表扫描,第二句使用了limit,则找到一个后就不再继续扫描。
- INDEX 全索引扫描,对索引从头到尾找一遍
- select nid from tb1;
- RANGE 对索引列进行范围查找
- select * from tb1 where name < 'alex';
- PS:
- between and
- in
- > >= < <= 操作
- 注意:!= 和 > 符号
- INDEX_MERGE 合并索引,使用多个单列索引搜索
- select * from tb1 where name = 'alex' or nid in (11,22,33);
- REF 根据索引查找一个或多个值
- select * from tb1 where name = 'seven';
- EQ_REF 连接时使用primary key 或 unique类型
- select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;
- CONST 常量
- 表最多有一个匹配行,因为仅有一行,在这行的列值可被优化器剩余部分认为是常数,const表很快,因为它们只读取一次。
- select nid from tb1 where nid = 2 ;
- SYSTEM 系统
- 表仅有一行(=系统表)。这是const联接类型的一个特例。
- select * from (select nid from tb1 where nid = 1) as A;
- possible_keys
- 可能使用的索引
- key
- 真实使用的
- key_len
- MySQL中使用索引字节长度
- rows
- mysql估计为了找到所需的行而要读取的行数 ------ 只是预估值
- extra
- 该列包含MySQL解决查询的详细信息
- “Using index”
- 此值表示mysql将使用覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。
- “Using where”
- 这意味着mysql服务器将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。
- “Using temporary”
- 这意味着mysql在对查询结果排序时会使用一个临时表。
- “Using filesort”
- 这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成。
- “Range checked for each record(index map: N)”
- 这个意味着没有好用的索引,新的索引将在联接的每一行上重新估算,N是显示在possible_keys列中索引的位图,并且是冗余的。
MYSQL进阶,新手变司机的更多相关文章
- 【转】MySQL— 进阶
[转]MySQL— 进阶 目录 一.视图 二.触发器 三.函数 四.存储过程 五.事务 一.视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需 ...
- MySQL进阶篇(03):合理的使用索引结构和查询
本文源码:GitHub·点这里 || GitEE·点这里 一.高性能索引 1.查询性能问题 在MySQL使用的过程中,所谓的性能问题,在大部分的场景下都是指查询的性能,导致查询缓慢的根本原因是数据量的 ...
- (6)MySQL进阶篇SQL优化(MyISAM表锁)
1.MySQL锁概述 锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源 (如 CPU.RAM.I/O 等)的抢占以外,数据也是一种供许多用户共享的资源.如何保证数 据并 ...
- mysql进阶(二十九)常用函数
mysql进阶(二十九)常用函数 一.数学函数 ABS(x) 返回x的绝对值 BIN(x) 返回x的二进制(OCT返回八进制,HEX返回十六进制) CEILING(x) 返回大于x的最小整数值 EXP ...
- mysql进阶(二十八)MySQL GRANT REVOKE用法
mysql进阶(二十八)MySQL GRANT REVOKE用法 MySQL的权限系统围绕着两个概念: 认证->确定用户是否允许连接数据库服务器: 授权->确定用户是否拥有足够的权限执 ...
- mysql进阶(二十七)数据库索引原理
mysql进阶(二十七)数据库索引原理 前言 本文主要是阐述MySQL索引机制,主要是说明存储引擎Innodb. 第一部分主要从数据结构及算法理论层面讨论MySQL数据库索引的数理基础. ...
- mysql进阶(二十六)MySQL 索引类型(初学者必看)
mysql进阶(二十六)MySQL 索引类型(初学者必看) 索引是快速搜索的关键.MySQL 索引的建立对于 MySQL 的高效运行是很重要的.下面介绍几种常见的 MySQL 索引类型. 在数 ...
- mysql进阶(十六)常见问题汇总
mysql进阶(十六)常见问题汇总 MySQL视图学习: http://www.itokit.com/2011/0908/67848.html 执行删除操作时,出现如下错误提示: 出现以上问题的原因是 ...
- MySQL进阶(视图)---py全栈
目录 mysql进阶(视图)---py全栈 一.什么是视图? 二.视图的特性 三.视图的优点 四.使用场合 五.视图基本操作 六.案例 mysql进阶(视图)---py全栈 一.什么是视图? 视图是从 ...
随机推荐
- MongoDB 创建 Database 和 Collection
在开始使用MongoDB(Version:3.2.9)之前,必须首先在MongoDB中创建 Database 和 Collection.Database是相互独立的,每个Database都有自己的Co ...
- distribution 中一直在运行 waitfor delay @strdelaytime 语句
Replication 自动创建来一个 Job:Replication monitoring refresher for distribution,这个Agent执行一个sp: dbo.sp_repl ...
- Caffe学习笔记2--Ubuntu 14.04 64bit 安装Caffe(GPU版本)
0.检查配置 1. VMWare上运行的Ubuntu,并不能支持真实的GPU(除了特定版本的VMWare和特定的GPU,要求条件严格,所以我在VMWare上搭建好了Caffe环境后,又重新在Windo ...
- ASP.NET MVC之如何看待内置配置来提高性能优化(四)
前言 前几篇我们比较基础的讲了下MVC中的知识,这一节我们穿插点知识,讲讲MVC中我们可以提高性能的办法. Razor视图引擎优化(优化一) 我们知道默认情况下配置MVC去解析一个视图会首先约定通过查 ...
- 应用程序框架实战十四:DDD分层架构之领域实体(基础篇)
上一篇,我介绍了自己在DDD分层架构方面的一些感想,本文开始介绍领域层的实体,代码主要参考自<领域驱动设计C#2008实现>,另外参考了网上找到的一些示例代码. 什么是实体 由标识来区分的 ...
- Java 线程池框架核心代码分析--转
原文地址:http://www.codeceo.com/article/java-thread-pool-kernal.html 前言 多线程编程中,为每个任务分配一个线程是不现实的,线程创建的开销和 ...
- C# 在word中查找及替换文本
C# 在word中查找及替换文本 在处理word文档时,很多人都会用到查找和替换功能.尤其是在处理庞大的word文档的时候,Microsoft word的查找替换功能就变得尤为重要,它不仅能让我们轻易 ...
- Word基础
1.页面设置 默认大小A4,长宽比0.618 页面布局 2.字体设置 选择要设置的字体->右键->字体 3.选择性粘贴 4.段落设置 选择文字->右键->段落 5.表格 =SU ...
- MySQL学习(二)SQL语句的总结
1.连接查询和关联查询连接查询:把两个表中相同的元素的连接就可以查询,使用:where里,select table1.*,table2.* from table1,table2 where table ...
- 优化JS加载时间过长的一种思路
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 去年公司在漳州的一个项目中,现场工程人员反映地图部分出图有点 ...