Views, triggers, transactions

view

  A SQL query result is a virtual table, it will be preserved this virtual table, it becomes a view.

  I'm the reason why we use a view, because when you frequently need to use multiple tables even when the results table, you can generate a good view in advance, directly after the call to avoid repeated write operations even table sql statement.

  Only table structure view, the data view or from the original table, do not change the data view of the table, as it will affect the next data in other tables generally do not frequent use views to write business logic.

  Fixed sentence

    create view with the name as the name of the back with a view of the virtual table (that is, the SQL statement to get a table)

trigger

  Reach a condition triggered automatically, when you are in the case of the data additions and deletions to run automatically trigger the trigger, similar to a warning system, is once you do an operation, I would immediately execute something.

Flip-flop into six cases: increased before; after growth; changing before; after the change; Truncate; after puncturing.
  Fixed grammatical structures:
  the Create the Trigger trigger name after / before insert / update / delete on the each table name Row for   
  the begin
  SQL statement
  end # ror each row is a real-time monitoring of meaning, as long as there is an increase in the data, changed or delete it immediately triggered

 

By former

  the Trigger tri_before the Create / after_insert / Update / delete_t1 the After / the before INSERT / Update / T1 ON the Delete Row for the each
  the begin
  SQL statements
  end
  can modify the default MySQL terminator (;)
  DELIMITER $$ # is valid only for the current window
  create trigger tri_before_insert_user before insert the User for the each Row ON
  the begin
  the SELECT * from the User
  End $$
  DELIMITER;

The CREATE TABLE cmd ( 
    ID the INT a PRIMARY KEY AUTO_INCREMENT, 
    the USER CHAR ( 32 ), 
    PRIV CHAR ( 10 ), 
    cmd CHAR ( 64 ), 
    SUB_TIME datetime, # submission time 
    Success enum ( ' Yes ' , ' NO ' ) # 0 Representative fails 
); 

the CREATE TABLE errlog ( 
    ID a PRIMARY KEY AUTO_INCREMENT the INT, 
    err_cmd CHAR ( 64 ), 
    err_time datetime 
); 

#   added: NEW to refer to the object is the current record 
delimiter $$ 
Create Trigger tri_after_insert_cmd After INSERT ON cmd for each row
begin
    if NEW.success = 'no' then
        insert into errlog(err_cmd,err_time) values(NEW.cmd,NEW.sub_time);
    end if;
end $$
delimiter ;




delimiter $$  # 只对当前窗口有效
create trigger tri_after_insert_user after insert on user for each row
begin
    insert into user(name,password) values('咻咻咻','123');
end $$
delimiter ;


drop trigger tri_before_insert_user;

 

Transaction:

Transaction contains a lot of sql statement, sql these at the same time either succeed, or even think about a success

  Four characteristics of the transaction: the ACID
    A: Atomicity
    C: Consistency
    I: Isolation
    D: Persistence

      Atomicity (atomicity). A transaction is an indivisible unit of work, all operations in the transaction include either do or do not do.
      Consistency (consistency). The database transaction must be changed from one consistent state to another consistent state. Consistency and atomicity are closely related.
      Isolation (isolation). Execution of a transaction can not be other transactions interference. I.e., operation and use of the data inside a transaction other concurrent transactions are isolated and can not interfere with each other between the respective transaction executed concurrently.
      Persistence (durability). Persistence also known as permanent (permanence), means that once a transaction commits, changing its data in the database should be permanent. The next operation or other faults should not have any effect on them .

How to open a transaction
  start transaction
transaction rollback
  rollback
permanent changes to
  commit

Stored Procedures

  Custom function is similar to the python, the sql statement inside the package database operations, want to achieve a corresponding subsequent operations can only call the stored procedure.

  create procedure pi () corresponds to the rear during storage means with parameters pi discharge function name parameter within the parentheses

# Syntax result 
        DELIMITER $$ 
        Create Procedure P1 () 
        the begin 
            SELECT * from User; 
        End $$ 
        DELIMITER; 

 #    arguments 
        DELIMITER $$ 
        Create Procedure P1 ( 
            in m int,   # can not be returned out 
            in n-int, 
            OUT RES int,   # can be returned 
            INOUT int xxx,   # both into and out may be 
        ) 
        the begin 
            the SELECT * from the User; 
        End $$ 
        DELIMITER;


$$ DELIMITER 
Create Procedure P1 ( 
    in m int,   # in this parameter indicates must be passed not only be returned out 
    in n-int, 
    OUT RES int   # OUT indicates that this parameter can be returned out, i.e., there may be expressed a inout incoming may be returned out 
) 
the begin 
    SELECT tname from Teacher WHERE TID> m and TID < n-; 
    SET RES = 0;   # is similar to a flag for identifying whether the memory is executed successfully 
End $$ 
DELIMITER; 

SET @res = 10    # set a binding relationship with the variable value of 

# to call a stored procedure variable @res pass 

# through and then returns the results select @res view the stored procedure is completed, the stored procedure library which can only be defined in the following in which use the following libraries

 

pymysql call a stored procedure:

import pymysql

conn = pymysql.connect(
    host = '127.0.0.1',
    port = 3306,
    user = 'root',
    password = '123',
    database = 'day38',
    charset = 'utf8',
    autocommit = True
)
cursor = conn.cursor(pymysql.cursors.DictCursor)
# call p1()  mysql中调用
# callproc()  pymysql中调用
cursor.callproc('p1',(1,5,10))
# 内部自动用变量名存储了对应的值
print(cursor.fetchall())

"""
@_p1_0=1
@_p1_1=5
@_p1_2=10
@_存储过程名_索引值
"""
cursor.execute('select @_p1_0')
print(cursor.fetchall())
cursor.execute('select @_p1_1')
print(cursor.fetchall())
cursor.execute('select @_p1_2')
print(cursor.fetchall())

 

存储过程与事务联合使用

delimiter //
create PROCEDURE p5(           #  创建一个存储器p5是名字
    OUT p_return_code tinyint    #   括号内是形参  OUT是能够被返回回来的
)
BEGIN               #  规定代码块儿

    DECLARE exit handler for sqlexception
    BEGIN
        -- ERROR     #   标识报错
        set p_return_code = 1;          #   如果出现报错了把返回值改成1
        rollback;
    END;


  DECLARE exit handler for sqlwarning   # 警告
  BEGIN
      -- WARNING
      set p_return_code = 2;   # 改成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中也叫做“键”,是存储引擎用于快速找到记录的一种数据结构。*

* primary key
* unique key
* index key

注意foreign key不是用来加速查询用的,不在我们研究范围之内,上面三种key前两种除了有加速查询的效果之外还有额外的约束条件(primary key:非空且唯一,unique key:唯一),而index key没有任何约束功能只会帮你加速查询

索引就是一种数据结构,类似于书的目录。意味着以后再查数据应该先找目录再找数据,而不是用翻页的方式查询数据

**本质都是:通过不断地缩小想要获取数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是说,有了这种索引机制,我们可以总是用同一种查找方式来锁定数据。**

**索引的影响:**

* 在表中有大量数据的前提下,创建索引速度会很慢
* 在索引创建完毕后,对表的查询性能会大幅度提升,但是写的性能会降低

 b+树

博客网址:  <https://images2017.cnblogs.com/blog/1036857/201709/1036857-20170912011123500-158121126.png>

只有叶子结点存放真实数据,根和树枝节点存的仅仅是虚拟数据

查询次数由树的层级决定,层级越低次数越少

一个磁盘块儿的大小是一定的,那也就意味着能存的数据量是一定的。如何保证树的层级最低呢?一个磁盘块儿存放占用空间比较小的数据项

思考我们应该给我们一张表里面的什么字段字段建立索引能够降低树的层级高度>>> 主键id字段

**聚集索引(primary key)**

聚集索引其实指的就是表的主键,innodb引擎规定一张表中必须要有主键。先来回顾一下存储引擎。

myisam在建表的时候对应到硬盘有几个文件(三个)?

innodb在建表的时候对应到硬盘有几个文件(两个)?frm文件只存放表结构,不可能放索引,也就意味着innodb的索引跟数据都放在idb表数据文件中。

**特点:**叶子结点放的一条条完整的记录

辅助索引(unique,index)

辅助索引:查询数据的时候不可能都是用id作为筛选条件,也可能会用name,password等字段信息,那么这个时候就无法利用到聚集索引的加速查询效果。就需要给其他字段建立索引,这些索引就叫辅助索引

**特点:**叶子结点存放的是辅助索引字段对应的那条记录的主键的值(比如:按照name字段创建索引,那么叶子节点存放的是:{name对应的值:name所在的那条记录的主键值})

select name from user where name='jason';

上述语句叫覆盖索引:只在辅助索引的叶子节点中就已经找到了所有我们想要的数据

select age from user where name='jason';

上述语句叫非覆盖索引,虽然查询的时候命中了索引字段name,但是要查的是age字段,所以还需要利用主键才去查找

 测试索引

**准备**

```mysql
#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();
```

``` mysql 
# 表没有任何索引的情况下
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字段一剑封喉
```

 联合索引

```mysql
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'; # 速度变快
```

总结:上面这些操作,你感兴趣可以敲一敲,不感兴趣你就可以不用敲了,权当看个乐呵。理论掌握了就行了

慢查询日志

设定一个时间检测所有超出改时间的sql语句,然后针对性的进行优化!

 

Guess you like

Origin www.cnblogs.com/sweet-i/p/11402603.html