MySQL의 트리거, 공정 제어, 및 기타 사항

  • 전망
  • 트리거
  • 사무
  • 저장 프로 시저
  • 내장 기능
  • 공정 제어
  • 색인

전망

1.보기는 무엇입니까

보기 저장 한 다음 가상 테이블을 조회하여 얻어지고, 다음 직접 사용할 수 있습니다

2, 왜보고해야

자주 가상 테이블을 사용하는 경우 쿼리를 반복 할 수 없습니다

3, 어떻게 볼 수 있습니다

create view teacher2course as
select * from teacher inner join course on teacher.tid = course.teacher_id;

스트레스
, 일을 하드 디스크에 테이블 구조를 데이터 파일 표뿐만 아니라 파일,보기
2, 뷰는 일반적으로 쿼리하는 데 사용됩니다, 데이터보기를 수정하지 않으려 고

drop view teacher2course;

질문 : 개발 과정이보기를 사용하는 것인가?

아니! 당신이보기 내 아이템을 많이 사용하는 경우 뷰, 함수 MySQL은, 즉 즉,이 함수의 기능은 MySQL은 여기에있을 필요 의미 뷰를 변경해야 할 일이 후자를 확장하고자 할 때 첫 번째보기는 조금 변경하고 부서 간 의사 소통의 문제에 관련된 SQL 문을 해당 응용 프로그램을 수정로 이동, 그래서 일반적으로보기를 사용하지 않지만, 재 편집 SQL 문을 통해 기능을 확장 할 수

트리거

데이터를 삭제, 변경, 추가 특정 테이블을 만족하는 경우에 자동적으로 트리거 함수를 호출 트리거

왜 트리거해야

우리의 데이터가 특정 테이블을 삭제, 삭제, 삽입을 추가 업데이트 동작을 변경을 위해 특별히 트리거, 행동의이 종류는 한 번만 실행
실행이 자동으로 코드 SQL의 다른 섹션을 실행하는 트리거를 트리거합니다

구문은 트리거를 만들 수 있습니다

# 针对插入
create trigger tri_after_insert_t1 after insert on 表名 for each row
begin
    sql代码。。。
end 
create trigger tri_after_insert_t2 before insert on 表名 for each row
begin
    sql代码。。。
end

# 针对删除
create trigger tri_after_delete_t1 after delete on 表名 for each row
begin
    sql代码。。。
end
create trigger tri_after_delete_t2 before delete on 表名 for each row
begin
    sql代码。。。
end

# 针对修改
create trigger tri_after_update_t1 after update on 表名 for each row
begin
    sql代码。。。
end
create trigger tri_after_update_t2 before update on 表名 for each row
begin
    sql代码。。。
end

# 案例
CREATE TABLE cmd (
    id INT PRIMARY KEY auto_increment,
    USER CHAR (32),
    priv CHAR (10),
    cmd CHAR (64),
    sub_time datetime, #提交时间
    success enum ('yes', 'no') #0代表执行失败
);

CREATE TABLE errlog (
    id INT PRIMARY KEY auto_increment,
    err_cmd CHAR (64),
    err_time datetime
);

delimiter $$  # 将mysql默认的结束符由;换成$$
create trigger tri_after_insert_cmd after insert on cmd for each row
begin
    if NEW.success = 'no' then  # 新记录都会被MySQL封装成NEW对象
        insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time);
    end if;
end $$
delimiter ;  # 结束之后记得再改回来,不然后面结束符就都是$$了

#往表cmd中插入记录,触发触发器,根据IF的条件决定是否插入错误日志
INSERT INTO cmd (
    USER,
    priv,
    cmd,
    sub_time,
    success
)
VALUES
    ('egon','0755','ls -l /etc',NOW(),'yes'),
    ('egon','0755','cat /etc/passwd',NOW(),'no'),
    ('egon','0755','useradd xxx',NOW(),'no'),
    ('egon','0755','ps aux',NOW(),'yes');

# 查询errlog表记录
select * from errlog;
# 删除触发器
drop trigger tri_after_insert_cmd;

사무

거래는 무엇인가

일부 SQL 문을 포함 할 수있는 트랜잭션을 열고 이러한 문 중 하나를 동시에 SQL 성공 있습니다
또는 성공적인 콜 거래 자성에 대해 생각

트랜잭션의 역할

이 데이터 조작에 대한 데이터 보안을 보장합니다

케이스 : 상거래 은행 ATM 기계의 은행 카드 작업을 사용하여 송금 계정

: 트랜잭션이 네 가지 속성이 있어야 자성, 일관성, 격리, 내구성. 이 네 가지 속성은 보통이라고 ACID 속성을 .

원 자성 (자성). 트랜잭션은 트랜잭션의 모든 작업 중 하나를 수행하거나하지 않는 등, 작업 단위입니다.

일관성 (일관성). 데이터베이스 트랜잭션은 다른 일관된 상태로 하나의 일관된 상태에서 변경해야합니다. 일관성 및 자성 밀접하게 관련되어있다.

절연 (절연). 트랜잭션의 실행은 다른 트랜잭션에 간섭 할 수 없다. 즉, 동작 및 다른 동시 트랜잭션 격리하고 동시에 실행되는 각 처리간에 서로 간섭 할 수없는 트랜잭션 내에서 데이터의 용도.

지속성 (내구성). 또한 영구 (내구성)라고도 지속성, 트랜잭션이 커밋되면, 데이터베이스의 데이터를 변경하는 영구되어야한다는 것을 의미한다. 다음 작업이나 다른 오류는 그들에 영향을주지해야한다.

방법

create table user(
id int primary key auto_increment,
name char(32),
balance int
);

insert into user(name,balance)
values
('wsb',1000),
('egon',1000),
('ysb',1000);

# 修改数据之前先开启事务操作
start transaction;

# 修改操作
update user set balance=900 where name='wsb'; #买支付100元
update user set balance=1010 where name='egon'; #中介拿走10元
update user set balance=1090 where name='ysb'; #卖家拿到90元

# 回滚到上一个状态
rollback;

# 开启事务之后,只要没有执行commit操作,数据其实都没有真正刷新到硬盘
commit;
"""开启事务检测操作是否完整,不完整主动回滚到上一个状态,如果完整就应该执行commit操作"""

# 站在python代码的角度,应该实现的伪代码逻辑,
try:
    update user set balance=900 where name='wsb'; #买支付100元
    update user set balance=1010 where name='egon'; #中介拿走10元
    update user set balance=1090 where name='ysb'; #卖家拿到90元
except 异常:
    rollback;
else:
    commit;

# 那如何检测异常?

저장 프로 시저

저장 프로 시저가 실행 SQL 문 시리즈를 포함, MySQL의에 저장된 저장 프로 시저, 당신은 그 이름을 호출하여 내부 SQL의 무리를 수행 할 수 있습니다

개발 모델의 세 가지

첫 번째

"""
应用程序:只需要开发应用程序的逻辑
mysql:编写好存储过程,以供应用程序调用
优点:开发效率,执行效率都高
缺点:考虑到人为因素、跨部门沟通等问题,会导致扩展性差
"""

두 번째

"""
应用程序:除了开发应用程序的逻辑,还需要编写原生sql
优点:比方式1,扩展性高(非技术性的)
缺点:
1、开发效率,执行效率都不如方式1
2、编写原生sql太过于复杂,而且需要考虑到sql语句的优化问题
"""

세 번째

"""
应用程序:开发应用程序的逻辑,不需要编写原生sql,基于别人编写好的框架来处理数据,ORM
优点:不用再编写纯生sql,这意味着开发效率比方式2高,同时兼容方式2扩展性高的好处
缺点:执行效率连方式2都比不过
"""

저장 프로 시저 만들기

delimiter $$
create procedure p1(
    in m int,  # in表示这个参数必须只能是传入不能被返回出去
    in n int,  
    out res int  # out表示这个参数可以被返回出去,还有一个inout表示即可以传入也可以被返回出去
)
begin
    select tname from teacher where tid > m and tid < n;
    set res=0;
end $$
delimiter ;

# 小知识点补充,当一张表的字段特别多记录也很多的情况下,终端下显示出来会出现显示错乱的问题
select * from mysql.user\G;

저장 프로 시저를 사용하는 방법

# 大前提:存储过程在哪个库下面创建的只能在对应的库下面才能使用!!!

# 1、直接在mysql中调用
set @res=10  # res的值是用来判断存储过程是否被执行成功的依据,所以需要先定义一个变量@res存储10
call p1(2,4,10);  # 报错
call p1(2,4,@res);  

# 查看结果
select @res;  # 执行成功,@res变量值发生了变化

# 2、在python程序中调用
pymysql链接mysql
产生的游表cursor.callproc('p1',(2,4,10))  # 内部原理:@_p1_0=2,@_p1_1=4,@_p1_2=10;
cursor.excute('select @_p1_2;')


# 3、存储过程与事务使用举例(了解)
delimiter //
create PROCEDURE p5(
    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;
      update user set balance=900 where id =1;
      update user123 set balance=1010 where id = 2;
      update user set balance=1090 where id =3;
  COMMIT;

  -- SUCCESS
  set p_return_code = 0; #0代表执行成功


END //
delimiter ;

기능

저장 프로 시저와의 차이, MySQL의 내장 기능은 SQL 문에주의!

참고 블로그 : http://www.cnblogs.com/linhaifeng/articles/7495918.html#_label2

CREATE TABLE blog (
    id INT PRIMARY KEY auto_increment,
    NAME CHAR (32),
    sub_time datetime
);

INSERT INTO blog (NAME, sub_time)
VALUES
    ('第1篇','2015-03-01 11:31:21'),
    ('第2篇','2015-03-11 16:31:21'),
    ('第3篇','2016-07-01 10:21:31'),
    ('第4篇','2016-07-22 09:23:21'),
    ('第5篇','2016-07-23 10:11:11'),
    ('第6篇','2016-07-25 11:21:31'),
    ('第7篇','2017-03-01 15:33:21'),
    ('第8篇','2017-03-01 17:32:21'),
    ('第9篇','2017-03-01 18:31:21');

select date_format(sub_time,'%Y-%m'),count(id) from blog group by date_format(sub_time,'%Y-%m');

공정 제어

# if条件语句
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 ;
# while循环
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 ;

느린 인덱싱 및 쿼리 최적화

지식 검토 : 데이터는 필연적으로 하드 디스크 IO 작업의 존재에 해당 쿼리 데이터가 필요하다

또한 "키"라는 MySQL의 인덱스에서 신속하게 기록을 찾는 데 사용하는 데이터 구조 스토리지 엔진이다.

  • 기본 키
  • 고유 키
  • 인덱스 키

(기본 키 외래 키 쿼리 속도를 높이기 위해 사용되지 않습니다, 우리는 키의 3 종류 전에 위의 두 가속 쿼리 결과뿐만 아니라 추가적인 제약뿐만 아니라, 연구의 범위 내에 있지 않은 : 비어 있지 만, 고유 키 : 어떤 제약 기능이없는 인덱스 키가 도움이 될 것입니다 동안 만), 당신은 쿼리 속도

인덱스는 디렉토리 북 유사한 데이터 구조입니다. 그것은 나중에 설문 조사 데이터는 데이터 디렉토리를 찾기 위해 먼저가 대신하는 방식의 데이터 페이지를 조회해야 의미

기본적으로 : 임의의 이벤트가 이벤트의 순서가 될 동안, 당신이 원하는 최종 결과를 얻을하려는 데이터의 연속 좁은 범위를 필터링하기 위해, 즉이 인덱싱 메커니즘, 말을하는 것입니다, 우리는 항상 사용할 수 있습니다 동일한 데이터를 잠글 수있는 방법을 찾을 수 있습니다.

영향력 지수 :

  • 인덱스를 생성하는 속도가 느려질 수 있습니다, 테이블에서 많은 양의 데이터의 가용성에 따라
  • 인덱스를 만든 후 테이블에 쿼리 성능이 크게 향상되지만, 쓰기 성능은 감소

ㄱ + 트리

https://images2017.cnblogs.com/blog/1036857/201709/1036857-20170912011123500-158121126.png

만 잎 노드는 실제 데이터, 뿌리와 가지 노드가 가상 데이터가 존재 저장

계층 적 의사 결정 트리로 문의의 수, 낮은 수준, 덜 자주

디스크 조각의 크기는 저장 될 수있는 데이터의 특정 량의 특정 방법이다. 어떻게 나무 그것의 최저 수준을 보장하기 위해? 디스크 저장 공간은 데이터 아이템의 상대적으로 작은 편이다

나는 우리가 우리에게 필드는 인덱스 트리의 높이의 수준을 줄일 수있는 내부 테이블을 제공해야한다고 생각 >>> 기본 키 ID 필드

클러스터 된 인덱스 (기본 키)

클러스터 인덱스는 실제로 테이블의 기본 키를 참조 테이블에 지정된 이노 엔진은 기본 키가 있어야합니다. 스토리지 엔진에서 첫 모습.

테이블의 구조는 하드 디스크에 해당하는의 MyISAM은 여러 개의 파일 (세)가?

테이블의 구조는 하드 디스크에 해당하는 InnoDB는 여러 개의 파일 (이)가? FRM 파일은 IDB가 테이블 데이터 파일에 데이터 이노 인덱스 수단 인덱스를 넣어 불가능 테이블 구조를 저장한다.

: 특징 넣어 리프 노드의 섹션의 전체 기록을

보조 인덱스 (고유 색인)

보조 인덱스 : 쿼리 데이터 모두도 등 정보 필드 이름, 암호를 사용할 수 있습니다, 선별 ID 조건으로 사용할 수 없습니다, 당신은 쿼리 성능 클러스터 된 인덱스 속도를 높이기 위해이 시간을 사용할 수 없습니다. 그것은 이러한 인덱스가 보조 인덱스라고하며, 다른 필드에 색인을 할 필요가

기능 : 리프 노드 (예를 들어, 상기 보조의 값에 대응하는 레코드 인덱스 필드의 기본 키에 저장된다 : 이름 필드 따른 인덱스 생성은, 그 리프 노드에 저장된다 : 값이 {명칭에 대응 : 기록이있는 것을 마스터의 이름 } 키)

어디 이름 = '제이슨'사용자의 이름을 선택;

위의 문은 커버링 인덱스라고 : 보조 인덱스의 리프 노드는 우리가 원하는 모든 데이터를 발견했다

어디 이름 = '제이슨'사용자의 나이를 선택;

위의 문은 호출되는 비 포함하는 인덱스가 쿼리 필드 이름을 쳤을 때,하지만, 인덱스를하지만 마스터 키를 사용하여 찾을 필요가 있으므로, age 필드하는지 확인

테스트 색인

준비된

#1. 准备表
create table s1(
id int,
name varchar(20),
gender char(6),
email varchar(50)
);

#2. 创建存储过程,实现批量插入记录
delimiter $$ #声明存储过程的结束符号为$$
create procedure auto_insert1()
BEGIN
    declare i int default 1;
    while(i<3000000)do
        insert into s1 values(i,'jason','male',concat('jason',i,'@oldboy'));
        set i=i+1;
    end while;
END$$ #$$结束
delimiter ; #重新声明分号为结束符号

#3. 查看存储过程
show create procedure auto_insert1\G 

#4. 调用存储过程
call auto_insert1();
# 表没有任何索引的情况下
select * from s1 where id=30000;
# 避免打印带来的时间损耗
select count(id) from s1 where id = 30000;
select count(id) from s1 where id = 1;

# 给id做一个主键
alter table s1 add primary key(id);  # 速度很慢

select count(id) from s1 where id = 1;  # 速度相较于未建索引之前两者差着数量级
select count(id) from s1 where name = 'jason'  # 速度仍然很慢


"""
范围问题
"""
# 并不是加了索引,以后查询的时候按照这个字段速度就一定快   
select count(id) from s1 where id > 1;  # 速度相较于id = 1慢了很多
select count(id) from s1 where id >1 and id < 3;
select count(id) from s1 where id > 1 and id < 10000;
select count(id) from s1 where id != 3;

alter table s1 drop primary key;  # 删除主键 单独再来研究name字段
select count(id) from s1 where name = 'jason';  # 又慢了

create index idx_name on s1(name);  # 给s1表的name字段创建索引
select count(id) from s1 where name = 'jason'  # 仍然很慢!!!
"""
再来看b+树的原理,数据需要区分度比较高,而我们这张表全是jason,根本无法区分
那这个树其实就建成了“一根棍子”
"""
select count(id) from s1 where name = 'xxx';  
# 这个会很快,我就是一根棍,第一个不匹配直接不需要再往下走了
select count(id) from s1 where name like 'xxx';
select count(id) from s1 where name like 'xxx%';
select count(id) from s1 where name like '%xxx';  # 慢 最左匹配特性

# 区分度低的字段不能建索引
drop index idx_name on s1;

# 给id字段建普通的索引
create index idx_id on s1(id);
select count(id) from s1 where id = 3;  # 快了
select count(id) from s1 where id*12 = 3;  # 慢了  索引的字段一定不要参与计算

drop index idx_id on s1;
select count(id) from s1 where name='jason' and gender = 'male' and id = 3 and email = 'xxx';
# 针对上面这种连续多个and的操作,mysql会从左到右先找区分度比较高的索引字段,先将整体范围降下来再去比较其他条件
create index idx_name on s1(name);
select count(id) from s1 where name='jason' and gender = 'male' and id = 3 and email = 'xxx';  # 并没有加速

drop index idx_name on s1;
# 给name,gender这种区分度不高的字段加上索引并不难加快查询速度

create index idx_id on s1(id);
select count(id) from s1 where name='jason' and gender = 'male' and id = 3 and email = 'xxx';  # 快了  先通过id已经讲数据快速锁定成了一条了
select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx';  # 慢了  基于id查出来的数据仍然很多,然后还要去比较其他字段

drop index idx_id on s1

create index idx_email on s1(email);
select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx';  # 快 通过email字段一剑封喉 

공동 색인

select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx';  
# 如果上述四个字段区分度都很高,那给谁建都能加速查询
# 给email加然而不用email字段
select count(id) from s1 where name='jason' and gender = 'male' and id > 3; 
# 给name加然而不用name字段
select count(id) from s1 where gender = 'male' and id > 3; 
# 给gender加然而不用gender字段
select count(id) from s1 where id > 3; 

# 带来的问题是所有的字段都建了索引然而都没有用到,还需要花费四次建立的时间
create index idx_all on s1(email,name,gender,id);  # 最左匹配原则,区分度高的往左放
select count(id) from s1 where name='jason' and gender = 'male' and id > 3 and email = 'xxx';  # 速度变快

요약 : 권리가 Lehe을 볼 때 이러한 작업을보다, 당신이하는, 당신에 관심이 관심이 노크 할 수 노크 노크 할 수 있습니다. 라인에 이론을 마스터

느린 쿼리 로그

모든 SQL 문을 검출 시간을 설정하면 시간 변경을 초과하고 최적화를 목표로!

추천

출처www.cnblogs.com/qianzhengkai/p/10881200.html