MySQL Explain简介及简单SQL优化_explain using join buffer-程序员宅基地

技术标签: Mysql  MySQL  Explain  SQL优化  

索引优化
数据准备

create table course
(
cid int(3),
cname varchar(20),
tid int(3)
);
create table teacher
(
    tid int(3),
    tname varchar(20),
    tcid int(3)
);
create table teachercard
(
tcid int(3),
tcdesc varchar(200)
);
insert into course values(1,'java',1);
insert into course values(2,'html',1);
insert into course values(3,'sql',2);
insert into course values(4,'web',3);
insert into teacher values(1,'tz',1);
insert into teacher values(2,'tw',2);
insert into teacher values(3,'tl',3);
insert into teachercard values(1,'tzdesc');
insert into teachercard values(2,'twdesc');
insert into teachercard values(3,'tidesc');

查询课程编号为2 或 教师证编号为3 的老师信息

mysql> explain select t.* from teacher t,course c,teachercard tc where t.tid=c.tid and t.tcid=tc.tcid and (c.cid=2 or tc.tcid=3);
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                              |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
|  1 | SIMPLE      | t     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | NULL                                               |
|  1 | SIMPLE      | tc    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |    33.33 | Using where; Using join buffer (Block Nested Loop) |
|  1 | SIMPLE      | c     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |    25.00 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+


(1)id: id 值相同,从上往下顺序执行,id 值不同,从大到小执行,t3-tc3-c4
    给teacher增加3条数据:

insert into teacher values(4,'ta',4);
insert into teacher values(5,'tb',5);
insert into teacher values(6,'tc',6);

mysql> explain select t.* from teacher t,course c,teachercard tc where t.tid=c.tid and t.tcid=tc.tcid and (c.cid=2 or tc.tcid=3);
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                              |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
|  1 | SIMPLE      | tc    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | NULL                                               |
|  1 | SIMPLE      | t     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    6 |    16.67 | Using where; Using join buffer (Block Nested Loop) |
|  1 | SIMPLE      | c     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |    25.00 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+

执行顺序变成了tc3-t6-c4

为什么执行顺序会变?原理?
因为数据量越小的越先执行。
原理:假设 a,b,c 3各表,数据量分别为 2 ,3 ,4 ,则笛卡尔积为  2 * 3 = 6 * 4 = 24
           如果设置  a为4条,b 为3 条,c为2条,        则笛卡尔积为 4 * 3 = 12 * 2 = 24
           虽然结果都是24,但中间结果一个是6,一个是12,中间结果越小越好。
           所以数据小的表 优先查询

 id 值不同:id值越大越先执行
 
 查询教授SQL磕碜的老师描述(desc)

select tc.* from teachercard tc,teacher t,course c where tc.tcid=t.tcid and t.tid=c.tid and c.cname='sql';
 子查询方式
 mysql> explain select tc.tcdesc from teachercard tc where tc.tcid=(select t.tcid from teacher t where t.tid=(select c.tid from course c where c.cname='sql'));
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | PRIMARY     | tc    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |    33.33 | Using where |
|  2 | SUBQUERY    | t     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    6 |    16.67 | Using where |
|  3 | SUBQUERY    | c     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |    25.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+

(2)select_type:
             PRIMARY:
             SUBQUERY:
             SIMPLE:简单查询(不包含子查询和union)

mysql> explain select * from course;
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | course | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |   100.00 | NULL  |
+----+-------------+--------+------------------+---------------+------+---------+------+------+----------+-------+

DERIVED:(使用到了临时表)如果在子查询中,table1 union table2,则table1 就是derived,table2为union

mysql> explain select cr.cname from ( select * from course where tid =1 union select * from course where tid=2 ) cr;
+----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type  | table      | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra           |
+----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
|  1 | PRIMARY      | <derived2> | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |   100.00 | NULL            |
|  2 | DERIVED      | course     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |    25.00 | Using where     |
|  3 | UNION        | course     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |    25.00 | Using where     |
| NULL | UNION RESULT | <union2,3> | NULL       | ALL  | NULL          | NULL | NULL    | NULL | NULL |     NULL | Using temporary |
+----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+


table中 derived2 表示 id=2 语句衍生出来的表
union2,3 表示id=2 和 id=3 的两张表进行union

union:看上例
union result: 看上例

(3) type:索引类型
    常见: system > const > eq_ref > ref > range > index > all  ,要对 type 进行优化,则前提是有索引
    其中: system,const 只是理想情况,实际能达到 ref > range

    system(忽略):只有一条数据的系统表;或 衍生表只有一条数据的主查询

    const:仅仅能查到一条数据的SQL,用于 primary key 或 unique 索引(与索引类型有关)
  

例:create table test01(tid int(3),tname varchar(20)); 
   insert into test01 values(1,'a');
   mysql> explain select * from (select * from test01) a  where tid=1;   ---tid为主键
+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table  | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | test01 | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

    如果是普通索引
    

mysql> explain select * from (select * from test01) a  where tid=1;
+----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+-------+
| id | select_type | table  | partitions | type | possible_keys | key    | key_len | ref   | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | test01 | NULL       | ref  | idxtid        | idxtid | 4       | const |    1 |   100.00 | NULL  |
+----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+-------+

    eq_ref:唯一索引,对于每个索引建的查询,返回匹配唯一行数据(有且只有1个,不能多,不能0),常见于索引列为主键或唯一索引。
    例:

mysql> explain select * from teacher t,teachercard tc where t.tcid=tc.tcid;   --t.tcid 唯一索引  tc.tcid 主键
+----+-------------+-------+------------+--------+---------------+------+---------+------------+------+----------+-------+
| id | select_type | table | partitions | type   | possible_keys | key  | key_len | ref        | rows | filtered | Extra |
+----+-------------+-------+------------+--------+---------------+------+---------+------------+------+----------+-------+
|  1 | SIMPLE      | tc    | NULL       | ALL    | PRIMARY       | NULL | NULL    | NULL       |    3 |   100.00 | NULL  |
|  1 | SIMPLE      | t     | NULL       | eq_ref | tcid          | tcid | 4       | ty.tc.tcid |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+--------+---------------+------+---------+------------+------+----------+-------+

 ref:非唯一索引,对于每个索引键的查询,返回匹配的所有行(0,多)

mysql> explain select * from teacher where tcid=1;      --tcid 辅助索引
+----+-------------+---------+------------+------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table   | partitions | type | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | teacher | NULL       | ref  | idxtcid       | idxtcid | 4       | const |    1 |   100.00 | NULL  |
+----+-------------+---------+------------+------+---------------+---------+---------+-------+------+----------+-------+

range:检索指定范围的行,where后面是一个范围查询(between,in, > ,>=, < ,<=, 其中 in 有可能失效)
        前提是where 的列必须有索引

index:查询全部索引中的数据,如果一个表中某一列a加了索引,则查的就是a这一列的所有数据,并不涉及到其他列
    

mysql> explain select tcid from teacher;  --tcid 为普通索引
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table   | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | teacher | NULL       | index | NULL          | idxtcid | 4       | NULL |    6 |   100.00 | Using index |
+----+-------------+---------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

    all:查询全部表中的数据

mysql> explain select tname from teacher;   --tname 无索引
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table   | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | teacher | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    6 |   100.00 | NULL  |
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------+

(4)possible_keys:可能用到的索引,是一种预测,不准
(5)key:实际用到的索引
(6)key_len:索引的长度,作用:用于判断符合索引是否被完全使用。
    

例:create table test_k1 (name char(20) not null default '');
    alter table test_k1 add index index_name(name);
    mysql> explain select * from test_k1 where name='';
+----+-------------+---------+------------+------+---------------+------------+---------+-------+------+----------+-------------+
| id | select_type | table   | partitions | type | possible_keys | key        | key_len | ref   | rows | filtered | Extra       |
+----+-------------+---------+------------+------+---------------+------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | test_k1 | NULL       | ref  | index_name    | index_name | 80      | const |    1 |   100.00 | Using index |
+----+-------------+---------+------------+------+---------------+------------+---------+-------+------+----------+-------------+


    这里 key_len 显示为 80,而建表的时候是20,因为字符集的原因,utf8mb4 一个字符占4个字节,所以这里80 = 20 * 4,说明 name索引列被使用 

在新增1列,并加上普通索引
 

alter table test_k1 add column name1 char(20); 
alter table test_k1 add index index_name1(name1);
mysql> explain select * from test_k1 where name1='';
+----+-------------+---------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
| id | select_type | table   | partitions | type | possible_keys | key         | key_len | ref   | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | test_k1 | NULL       | ref  | index_name1   | index_name1 | 81      | const |    1 |   100.00 | NULL  |
+----+-------------+---------+------------+------+---------------+-------------+---------+-------+------+----------+-------+

 为什么name1同样是20个字符,而key_len=81?
 因为name列定义的是不能为空,而name1可以为空,如果栏位定义为可以为空,则需要多占一个1字节用于标示可以为空,所以是81.
    

删掉索引
drop index index_name on test_k1;drop index index_name1 on test_k1;
创建复合索引
alter table test_k1 add index index_name_name1(name,name1);
mysql> explain select * from test_k1 where name1='';
+----+-------------+---------+------------+-------+---------------+------------------+---------+------+------+----------+--------------------------+
| id | select_type | table   | partitions | type  | possible_keys | key              | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+---------+------------+-------+---------------+------------------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | test_k1 | NULL       | index | NULL          | index_name_name1 | 161     | NULL |    1 |   100.00 | Using where; Using index |
+----+-------------+---------+------------+-------+---------------+------------------+---------+------+------+----------+--------------------------+


    为什么key_len=161?
    因为条件是name1='',而name和name1是复合索引,所以要用name1则必须要用name,所以 80 + 81 = 161
    在新增1列,并加上普通索引
    

alter table test_k1 add column name2 varchar(20); 
alter table test_k1 add index index_name2(name2);

mysql> explain select * from test_k1 where name2='';
+----+-------------+---------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
| id | select_type | table   | partitions | type | possible_keys | key         | key_len | ref   | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | test_k1 | NULL       | ref  | index_name2   | index_name2 | 83      | const |    1 |   100.00 | NULL  |
+----+-------------+---------+------------+------+---------------+-------------+---------+-------+------+----------+-------+


    key_len 为什么等于 83?
    因为name2为可变长度,可变长度要用2个字节标示。 80 + 1(null) + 2(可变) = 83

    utf8:1个字符占3个字节
    utf8mb4:1个字符占4个字节
    gbk:1个字符占2个字节
    latin:1个字符占1个字节


(7)ref:指明当前表所参照的字段。
        select .... where a.c = b.x;  则 a 表应用了 b.x,如果 b.x 为常量,则ref的值为const。

mysql> explain select * from teacher t ,course c where t.tid=c.tid and t.tname='tw'; -- t.tid 主键,c.tid 普通索引,t.tname 普通索引
+----+-------------+-------+------------+------+-------------------+-----------+---------+----------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys     | key       | key_len | ref      | rows | filtered | Extra |
+----+-------------+-------+------------+------+-------------------+-----------+---------+----------+------+----------+-------+
|  1 | SIMPLE      | t     | NULL       | ref  | PRIMARY,idx_tname | idx_tname | 83      | const    |    1 |   100.00 | NULL  |
|  1 | SIMPLE      | c     | NULL       | ref  | idx_tid           | idx_tid   | 5       | ty.t.tid |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+-------------------+-----------+---------+----------+------+----------+-------+


    第一条,因为 t.tname ='tw' 为常量,所以这里ref 为 const
    第二条,因为 c 表引用了 ty.t.tid 作为条件,所以这里 ref 为 ty.t.tid


(8)rows:被索引优化查询的数据个数(索引优化后的结果有多少条数据)

(9)Extra:
    (i)using filesort: 性能消耗大;需要“额外”的一次排序(查询)。常见于 order by 语句中 
        

例:
create table test01(a1 char(3),a2 char(3),a3 char(3),index idx_a1(a1),index idx_a2(a2),index idx_a3(a3));
mysql> explain select * from test02 where a1='' order by a1;
    +----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+-------+
    | id | select_type | table  | partitions | type | possible_keys | key    | key_len | ref   | rows | filtered | Extra |
    +----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+-------+
    |  1 | SIMPLE      | test02 | NULL       | ref  | idx_a1        | idx_a1 | 13      | const |    1 |   100.00 | NULL  |
    +----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+-------+


        为什么没有出现using filesort?
        因为 where 的条件跟 order by 的列是同一列。
        先根据 where 条件查出满足条件的数据,且a1是索引,查出来的数据本来就是排序好的,而order by 正好是按照a1排序,所以不会在需要 “额外”的一次排序(查询)


      

 mysql> explain select * from test02 where a1='' order by a2;
    +----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+---------------------------------------+
    | id | select_type | table  | partitions | type | possible_keys | key    | key_len | ref   | rows | filtered | Extra                                 |
    +----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+---------------------------------------+
    |  1 | SIMPLE      | test02 | NULL       | ref  | idx_a1        | idx_a1 | 13      | const |    1 |   100.00 | Using index condition; Using filesort |
    +----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+---------------------------------------+


        为什么出现using filesort?
        因为 where 的条件跟 order by 的列不是同一列。
        先根据 where 条件查出满足条件的数据,且a1是索引,查出来的数据是按照 a1 列排序的,而order by 的却是 a2,如果需要按照 a2 来排序,则需要多 “额外”的再按照 a2 排一次序(查询)

        符合索引:不能跨列(最佳左前缀)
        

mysql> explain select * from test02 where a1='' order by a3;
    +----+-------------+--------+------------+------+---------------+------------+---------+-------+------+----------+------------------------------------------+
    | id | select_type | table  | partitions | type | possible_keys | key        | key_len | ref   | rows | filtered | Extra                                    |
    +----+-------------+--------+------------+------+---------------+------------+---------+-------+------+----------+------------------------------------------+
    |  1 | SIMPLE      | test02 | NULL       | ref  | idx_a1a2a3    | idx_a1a2a3 | 13      | const |    1 |   100.00 | Using where; Using index; Using filesort |
    +----+-------------+--------+------------+------+---------------+------------+---------+-------+------+----------+------------------------------------------+


        为什么会出现using filesort?
        因为建的是符合索引,a1 a3,中间少了a2.

        

mysql> explain select * from test02 where a1='' order by a2;
    +----+-------------+--------+------------+------+---------------+------------+---------+-------+------+----------+--------------------------+
    | id | select_type | table  | partitions | type | possible_keys | key        | key_len | ref   | rows | filtered | Extra                    |
    +----+-------------+--------+------------+------+---------------+------------+---------+-------+------+----------+--------------------------+
    |  1 | SIMPLE      | test02 | NULL       | ref  | idx_a1a2a3    | idx_a1a2a3 | 13      | const |    1 |   100.00 | Using where; Using index |
    +----+-------------+--------+------------+------+---------------+------------+---------+-------+------+----------+--------------------------+


        这里是a1 和 a2,没有跨列

        小结:
        单索引情况下: where 哪些字段就 order by 哪些字段
        复合索引情况: where + order by 的栏位 按照复合索引的顺序使用,不要无序或跨列使用

    (ii) using temporary :性能损耗大,用到了临时表。常见于 group by 语句中
      

 例:mysql> explain select a1 from test02 where a1 in ('1','2') group by a2;
    +----+-------------+--------+------------+-------+---------------+------------+---------+------+------+----------+-----------------------------------------------------------+
    | id | select_type | table  | partitions | type  | possible_keys | key        | key_len | ref  | rows | filtered | Extra                                                     |
    +----+-------------+--------+------------+-------+---------------+------------+---------+------+------+----------+-----------------------------------------------------------+
    |  1 | SIMPLE      | test02 | NULL       | index | idx_a1a2a3    | idx_a1a2a3 | 39      | NULL |    1 |   100.00 | Using where; Using index; Using temporary; Using filesort |
    +----+-------------+--------+------------+-------+---------------+------------+---------+------+------+----------+-----------------------------------------------------------+


        避免:查询哪些列,就根据那些列group by


    (iii) using index:性能提升:索引覆盖(覆盖索引)。原因:不读取源文件,只从索引文件中获取数据(不需要回表查询)
                只要使用到的列,全部都在索引中,就是索引覆盖
            

mysql> explain select a1,a2 from test02 where a1='' and a2='';
        +----+-------------+--------+------------+------+---------------+----------+---------+-------------+------+----------+-------------+
        | id | select_type | table  | partitions | type | possible_keys | key      | key_len | ref         | rows | filtered | Extra       |
        +----+-------------+--------+------------+------+---------------+----------+---------+-------------+------+----------+-------------+
        |  1 | SIMPLE      | test02 | NULL       | ref  | idx_a1a2      | idx_a1a2 | 26      | const,const |    1 |   100.00 | Using index |
        +----+-------------+--------+------------+------+---------------+----------+---------+-------------+------+----------+-------------+


        因为这里where 就是 a1 和 a2, 查的也是 a1 和 a2,故可以使用索引覆盖。


        

mysql> explain select a1,a3 from test02 where a1='' and a2='';
        +----+-------------+--------+------------+------+---------------+----------+---------+-------------+------+----------+-------+
        | id | select_type | table  | partitions | type | possible_keys | key      | key_len | ref         | rows | filtered | Extra |
        +----+-------------+--------+------------+------+---------------+----------+---------+-------------+------+----------+-------+
        |  1 | SIMPLE      | test02 | NULL       | ref  | idx_a1a2      | idx_a1a2 | 26      | const,const |    1 |   100.00 | NULL  |
        +----+-------------+--------+------------+------+---------------+----------+---------+-------------+------+----------+-------+


        因为这里where 就是 a1 和 a2, 但查的是 a1 和 a3,故不可以使用索引覆盖。

        如果用到了索引覆盖,会对 possible_keys 和 key 造成影响:
            a.如果没有where,则索引只出现在keys中;
            b.如果有where,则索引出现在key 和possible_keys中。


    (iv)using where(需要回表查询)
            假设age是索引列
            但查询语句 select age,name from ...where age=...此语句中必须会原表查name,因此会显示using where

    (iv)impossible where:where 字句永远为false

例: mysql> explain select a3 from test02 where a1='' and a1='1';
        +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
        | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra            |
        +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
        |  1 | SIMPLE      | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | Impossible WHERE |
        +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
create table test03(
a1 int(4) not null,
a2 int(4) not null,
a3 int(4) not null,
a4 int(4) not null);
alter table test03 add index idx_a14(a1,a2,a3,a4);

mysql> explain select a1,a2,a3,a4 from test03 where a1=1 and a2=2 and a4=3 order by  a3;
+----+-------------+--------+------------+------+---------------+---------+---------+-------------+------+----------+--------------------------+
| id | select_type | table  | partitions | type | possible_keys | key     | key_len | ref         | rows | filtered | Extra                    |
+----+-------------+--------+------------+------+---------------+---------+---------+-------------+------+----------+--------------------------+
|  1 | SIMPLE      | test03 | NULL       | ref  | idx_a14       | idx_a14 | 8       | const,const |    1 |   100.00 | Using where; Using index |
+----+-------------+--------+------------+------+---------------+---------+---------+-------------+------+----------+--------------------------+

        以上SQL用到了a1,a2两个索引,该2个字段不需要回表查询,所以using index,而a4因为跨列了使用,造成该索引失效,需要回表查询,因此是using where,以上可以通过key_len看出。

mysql> explain select a1,a2,a3,a4 from test03 where a1=1  and a4=3 order by  a3;
+----+-------------+--------+------------+------+---------------+---------+---------+-------+------+----------+------------------------------------------+
| id | select_type | table  | partitions | type | possible_keys | key     | key_len | ref   | rows | filtered | Extra                                    |
+----+-------------+--------+------------+------+---------------+---------+---------+-------+------+----------+------------------------------------------+
|  1 | SIMPLE      | test03 | NULL       | ref  | idx_a14       | idx_a14 | 4       | const |    1 |   100.00 | Using where; Using index; Using filesort |
+----+-------------+--------+------------+------+---------------+---------+---------+-------+------+----------+------------------------------------------+

    为什么这里出现了using filesort,而上面一句没出现?
    因为上句中 a1、a2 (a4失效,因为不连续)+ order by 的a3 ,是连续的,没有跨列。
    而下句中 a1、(a4失效,不连续) + order by 的 a3,中间少了a2,跨列了
    原理:因为a1,a2,a3,a4 是复合索引,所以上句中,根据 a1 和 a2 过滤出来的 a3,a4 的数据是排序好的,然后通过a4=3在过滤下,就ok了,不需要在额外排序了。
    而下句中,根据 a1 过滤出来的 a2 和 a3 是顺序的,但是排序的是按照 a3 ,中间少了a2,所以单独看a3不是顺序的,所以要额外进行一次排序

     总结:i.如果(a,b,c,d)符合索引和使用的顺序全部一致(且不跨列使用),则复合索引全部使用。如果部分一致(且不跨列使用),则使用部分索引。
         ii.where 和order 拼起来,不要跨列使用优化案例
    单表优化、2表优化、3表优化
    

(1)单表优化
create table book(
bid int(4) primary key,
name varchar(20) not null, 
authorid int(4) not null,
publicid int(4) not null,
typeid int(4) not null);
insert into book values(1,'tjava',1,1,2);
insert into book values(2,'tc',2,1,2);
insert into book values(3,'wx',3,2,1);
insert into book values(4,'math',4,2,3);

mysql> explain select bid from book where typeid in(2,3) and authorid=1 order by typeid desc;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                       |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------------------+
    |  1 | SIMPLE      | book  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |    25.00 | Using where; Using filesort |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------------------+

    

优化:加索引
alter table book add index idx_bta(bid,typeid,authorid);   --因为顺序是bid,typeid,authorid

mysql> explain select bid from book where typeid in(2,3) and authorid=1 order by typeid desc;
    +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+------------------------------------------+
    | id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                                    |
    +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+------------------------------------------+
    |  1 | SIMPLE      | book  | NULL       | index | NULL          | idx_bta | 12      | NULL |    4 |    25.00 | Using where; Using index; Using filesort |
    +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+------------------------------------------+


        这里 type 从 all 变成了 index,性能有所提升,但不理想,还有using filesort 和 using where 存在

        这里要提出的是上面建的符合索引不合理,因为根据sql语句的解析过程 :
        from .. on .. join .. where .. group by .. having .. select .. distinct .. order by .. limit
        可以看出 select 是在where后面的,所以复合索引的顺序应修改为 typeid,authorid,bid
        索引一旦进行升级优化,需要将之前废弃的索引删掉,防止干扰
        alter table book add index idx_tab(typeid,authorid,bid);
        可能有的会说有了typeid和authorid就行了,bid可以通过回表来查,但是,如果把bid也加进来的话可以使用using index,性能可以有一定的提升
        

mysql> explain select bid from book where typeid in(2,3) and authorid=1 order by typeid desc;
    +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
    | id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                    |
    +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
    |  1 | SIMPLE      | book  | NULL       | range | idx_tab       | idx_tab | 8       | NULL |    2 |   100.00 | Using where; Using index |
    +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+

        这里将 using filesort 优化掉了

        因为 如果使用in的话,可能导致索引失效,所以将authorid 和 typeid 的位置互换(索引也换) 

mysql> explain select bid from book where authorid=1 and typeid in(2,3) order by typeid desc;
    +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
    | id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                    |
    +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
    |  1 | SIMPLE      | book  | NULL       | range | idx_tab       | idx_tab | 8       | NULL |    2 |   100.00 | Using where; Using index |
    +----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+

         这里还是 using where;using index的原因?
        因为authorid=1 因为在索引列最左边,可以使用索引覆盖
        而typeid 因为使用的in,所以 typeid的索引失效,故需要回表,所以出现using where,从 key_len =8 就可以看出只使用到了1个列

        将typeid in(2,3) 换成 typeid=3进行验证:

mysql> explain select bid from book where  authorid=1 and typeid =3 order by typeid desc;
    +----+-------------+-------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+
    | id | select_type | table | partitions | type | possible_keys | key     | key_len | ref         | rows | filtered | Extra       |
    +----+-------------+-------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+
    |  1 | SIMPLE      | book  | NULL       | ref  | idx_tab       | idx_tab | 8       | const,const |    1 |   100.00 | Using index |
    +----+-------------+-------+------------+------+---------------+---------+---------+-------------+------+----------+-------------+

       这里using where 消失,


        总结:
            a.最佳左前缀,保持索引的定义和使用顺序要一致,不能跨列
            b.索引需要逐步优化
            c.将含 in 的范围查询,放到where 条件的最后,防止索引失效
    (2)2表优化
        例: 
        

create table teacher2(
tid int(4) primary key,
cid int (4) not null);

create table course2(cid int(4) ,cname varchar(20));
insert into teacher2 values(1,2);
insert into teacher2 values(2,1);
insert into teacher2 values(3,3);
insert into course2 values(1,'java');
insert into course2 values(2,'python');
insert into course2 values(3,'kotlin');

mysql> explain select * from teacher2 t left outer join course2 c on t.cid=c.cid where c.cname='java';
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                              |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
    |  1 | SIMPLE      | c     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |    33.33 | Using where                                        |
    |  1 | SIMPLE      | t     | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |    33.33 | Using where; Using join buffer (Block Nested Loop) |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+


        索引往哪张表加?
        左外连接时(left outer join),给左边的表加索引,同理右外连接给右边的表加索引,总之就是在使用较频繁的字段上加索引,比如小表10条数据,大表100条数据,如果
        .. on 小表.c = 大表.c ,则小表的c字段每一条记录都要跟 大表.c 字段比对100次,故小表.c字段使用频繁,故在小表.c 字段上加索引

        结论:1.当编写 。。 on t.cid=c.cid 时,往往将数据量小的表放左边
              
        小表驱动大表

        增加索引
        

mysql> alter table teacher2 add index idx_cid(cid);
       alter table course2 add index idx_cname(cname);
mysql> explain select * from teacher2 t left outer join course2 c on t.cid=c.cid where c.cname='java';
        +----+-------------+-------+------------+------+---------------+---------+---------+----------+------+----------+-------------+
        | id | select_type | table | partitions | type | possible_keys | key     | key_len | ref      | rows | filtered | Extra       |
        +----+-------------+-------+------------+------+---------------+---------+---------+----------+------+----------+-------------+
        |  1 | SIMPLE      | c     | NULL       | ALL  | NULL          | NULL    | NULL    | NULL     |    3 |    33.33 | Using where |
        |  1 | SIMPLE      | t     | NULL       | ref  | idx_cid       | idx_cid | 4       | ty.c.cid |    1 |   100.00 | Using index |
        +----+-------------+-------+------------+------+---------------+---------+---------+----------+------+----------+-------------+

        
mysql> explain select * from teacher2 t left outer join course2 c on t.cid=c.cid where c.cname='java';
        +----+-------------+-------+------------+------+---------------+-----------+---------+----------+------+----------+-------------+
        | id | select_type | table | partitions | type | possible_keys | key       | key_len | ref      | rows | filtered | Extra       |
        +----+-------------+-------+------------+------+---------------+-----------+---------+----------+------+----------+-------------+
        |  1 | SIMPLE      | c     | NULL       | ref  | idx_cname     | idx_cname | 83      | const    |    1 |   100.00 | Using where |
        |  1 | SIMPLE      | t     | NULL       | ref  | idx_cid       | idx_cid   | 4       | ty.c.cid |    1 |   100.00 | Using index |
        +----+-------------+-------+------------+------+---------------+-----------+---------+----------+------+----------+-------------+

    (3)三张表优化
            a.小表驱动大表
            b.索引建立在经常查询的字段上

7.避免索引失效的一些原则 
    (1)复合索引
        a.复合索引,不要跨列或无需使用(最佳左前缀,如果最左边失效,则后面的全部失效)
        b.复合索引,尽量使用全索引匹配
    (2)不要在索引上进行任何操作(计算、函数、类型转换),否则索引失效
        不要:select ... where a.x * 3 =
    (3)复合索引不能使用不等于(!= 或 <> ) 或 is null (is not null,否则自身以及右侧全部失效
    (4)体验概率情况(<  >  =):原因是服务层中有SQL优化器,可能会影响我们的优化。
    

mysql> explain select * from book where authorid>1 and typeid=1;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
    |  1 | SIMPLE      | book  | NULL       | ALL  | idxat         | NULL | NULL    | NULL |    4 |    25.00 | Using where |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+


        复合索引不能使用 >  ,否则自身及右边的索引失效        

mysql> explain select * from book where authorid<1 and typeid=2;
    +----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+-----------------------+
    | id | select_type | table | partitions | type  | possible_keys | key   | key_len | ref  | rows | filtered | Extra                 |
    +----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+-----------------------+
    |  1 | SIMPLE      | book  | NULL       | range | idxat         | idxat | 4       | NULL |    1 |    25.00 | Using index condition |
    +----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+-----------------------+


mysql> explain select * from book where authorid<4 and typeid=2;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
    | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
    |  1 | SIMPLE      | book  | NULL       | ALL  | idxat         | NULL | NULL    | NULL |    4 |    25.00 | Using where |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+


        上面2个sql完全一样,只是authorid 1 改成了4 ,但执行计划不一样,所以在有 > 、 < 、 = 的时候有概率跟你想的优化结果不一样

    索引优化,是一个大部分情况适用的结论,但由于SQL优化器等原因,该结论不是100%正确。
    一般而言,范围查询(< 、 > 、 in),之后的索引失效。

    (5)补救:尽量使用索引覆盖(using index)
    (6)like尽量以“常量”开头,不要以“%”开头,否则索引失效
    (7)不要类型转换(显示、隐士)
        

mysql> explain select * from teacher where tname='ab';
        +----+-------------+---------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
        | id | select_type | table   | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra |
        +----+-------------+---------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
        |  1 | SIMPLE      | teacher | NULL       | ref  | idx_tname     | idx_tname | 83      | const |    1 |   100.00 | NULL  |
        +----+-------------+---------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
        
mysql> explain select * from teacher where tname=123;
        +----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+
        | id | select_type | table   | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
        +----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+
        |  1 | SIMPLE      | teacher | NULL       | ALL  | idx_tname     | NULL | NULL    | NULL |    6 |    16.67 | Using where |
        +----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+


        tname为varchar(20)
        下句中,tname=123,程序将数字123 转换成了字符串‘123’,及类型转换,造成索引失效
    (8)尽量不要使用or,否则索引失效
        

mysql> explain select * from teacher where tname='' and tcid >1;
        +----+-------------+---------+------------+------+-------------------+-----------+---------+-------+------+----------+-------------+
        | id | select_type | table   | partitions | type | possible_keys     | key       | key_len | ref   | rows | filtered | Extra       |
        +----+-------------+---------+------------+------+-------------------+-----------+---------+-------+------+----------+-------------+
        |  1 | SIMPLE      | teacher | NULL       | ref  | idxtcid,idx_tname | idx_tname | 83      | const |    1 |    83.33 | Using where |
        +----+-------------+---------+------------+------+-------------------+-----------+---------+-------+------+----------+-------------+
        

mysql> explain select * from teacher where tname='' or tcid >1;  --将or 左侧的tname索引也失效
        +----+-------------+---------+------------+------+-------------------+------+---------+------+------+----------+-------------+
        | id | select_type | table   | partitions | type | possible_keys     | key  | key_len | ref  | rows | filtered | Extra       |
        +----+-------------+---------+------------+------+-------------------+------+---------+------+------+----------+-------------+
        |  1 | SIMPLE      | teacher | NULL       | ALL  | idxtcid,idx_tname | NULL | NULL    | NULL |    6 |    44.44 | Using where |
        +----+-------------+---------+------------+------+-------------------+------+---------+------+------+----------+-------------+

8.一些其他的优化方法
        a.exist 和 in    
        如果主查询的数据集大,则使用 in
        如果子查询的数据集大,则使用exist

        b.order by 优化掉了
            >调整max_lenght_for_sort_buffer 大小,选择回表排序或非回表排序(需要排序的字段的总大小大于调整max_lenght_for_sort_buffer,则是回表排序\
            >避免 select *......
            >复合索引 不要跨列使用,避免using filesort
            > 保证全部的排序字段排序一致性(都是升序或降序)


结论:
1.id值相同,从上到下顺序执行,id值不同,从大到小顺序执行
2.system/const :结果只有一条数据
  eq_ref:结果多条,但是每条数据是唯一的
  ref:结果多条,但是每条数据时0或多条
3.using filesort 如何避免?
    单索引情况下: where 哪些字段就 order by 哪些字段
    复合索引情况: where + order by 的栏位 按照复合索引的顺序使用,不要无序或跨列使用
4.using temporary 如何避免?
    查询哪些列,就根据那些列group by
5.符合索引不要跨列、无需使用。
6.最佳左前缀,保持索引的定义和使用顺序要一致,不能跨列
7.索引需要逐步优化
8.将含 in 的范围查询,放到where 条件的最后,防止索引失效
9.两表连接时,索引往哪张表加?
    左外连接时(left outer join),给左边的表加索引,同理右外连接给右边的表加索引,总之就是在使用较频繁的字段上加索引,比如小表10条数据,大表100条数据,如果
    .. on 小表.c = 大表.c ,则小表的c字段每一条记录都要跟 大表.c 字段比对100次,故小表.c字段使用频繁,故在小表.c 字段上加索引
10.当编写 。。 on t.cid=c.cid 时,往往将数据量小的表放左边
11.小表驱动大表
12.exist 和 in,    如果主查询的数据集大,则使用 in,    如果子查询的数据集大,则使用exist
13.order by 优化
    >调整max_lenght_for_sort_buffer 大小,选择回表排序或非回表排序(需要排序的字段的总大小大于调整max_lenght_for_sort_buffer,则是回表排序\
    >避免 select *......
    >复合索引 不要跨列使用,避免using filesort
    > 保证全部的排序字段排序一致性(都是升序或降序)
14.尽量不要使用or,否则索引失效
15.尽量使用索引覆盖(using index)
16.like尽量以“常量”开头,不要以“%”开头,否则索引失效
17.不要类型转换(显示、隐士)
18.三张表优化。a.小表驱动大表;    b.索引建立在经常查询的字段上
19.避免索引失效的一些原则 
    (1)复合索引
        a.复合索引,不要跨列或无需使用(最佳左前缀,如果最左边失效,则后面的全部失效)
        b.复合索引,尽量使用全索引匹配
    (2)不要在索引上进行任何操作(计算、函数、类型转换),否则索引失效
        不要:select ... where a.x * 3 =
    (3)复合索引不能使用不等于(!= 或 <> ) 或 is null (is not null,否则自身以及右侧全部失效
    (4)体验概率情况(<  >  =):原因是服务层中有SQL优化器,可能会影响我们的优化。
20.将含 in 的范围查询,放到where 条件的最后,防止索引失效

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


SQL优化,主要就是索引优化
索引的弊端:
    1.索引本身很大,可以存放在内存/硬盘(通常为硬盘)
    2.索引不是所有情况均适用:
        a.数据量小  
        b.频繁更新的字段。因为如果索引字段频繁更新,则会导致索引的结构频繁变更,维护成本太高
        c.很少使用的字段。因为不需要查(或者很少查),所以不必建索引
    3.索引会降低增删改的效率。
        如果没有索引,则直接找到需要增删改的数据修改即可。
        如果有索引,不光要改数据,还有修改索引的结构,所以会影响增删改的效率。

优势:
    1.提高查询效率(实质就是降低IO使用率)
    2.降低CPU使用率(....order by .. asc/desc,因为B 树索引本身就是一个排好序的结构,因此在排序的时候可以直接使用)

 

如理解有误,请多指正,感谢!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_31144297/article/details/103778461

智能推荐

分布式光纤传感器的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告_预计2026年中国分布式传感器市场规模有多大-程序员宅基地

文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大

07_08 常用组合逻辑电路结构——为IC设计的延时估计铺垫_基4布斯算法代码-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码

OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版-程序员宅基地

文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版

关于美国计算机奥赛USACO,你想知道的都在这_usaco可以多次提交吗-程序员宅基地

文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗

MySQL存储过程和自定义函数_mysql自定义函数和存储过程-程序员宅基地

文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程

半导体基础知识与PN结_本征半导体电流为0-程序员宅基地

文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0

随便推点

【Unity3d Shader】水面和岩浆效果_unity 岩浆shader-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader

广义线性模型——Logistic回归模型(1)_广义线性回归模型-程序员宅基地

文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型

HTML+CSS大作业 环境网页设计与实现(垃圾分类) web前端开发技术 web课程设计 网页规划与设计_垃圾分类网页设计目标怎么写-程序员宅基地

文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写

C# .Net 发布后,把dll全部放在一个文件夹中,让软件目录更整洁_.net dll 全局目录-程序员宅基地

文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录

BRIEF特征点描述算法_breif description calculation 特征点-程序员宅基地

文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点

房屋租赁管理系统的设计和实现,SpringBoot计算机毕业设计论文_基于spring boot的房屋租赁系统论文-程序员宅基地

文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文