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

智能推荐

hive使用适用场景_大数据入门:Hive应用场景-程序员宅基地

文章浏览阅读5.8k次。在大数据的发展当中,大数据技术生态的组件,也在不断地拓展开来,而其中的Hive组件,作为Hadoop的数据仓库工具,可以实现对Hadoop集群当中的大规模数据进行相应的数据处理。今天我们的大数据入门分享,就主要来讲讲,Hive应用场景。关于Hive,首先需要明确的一点就是,Hive并非数据库,Hive所提供的数据存储、查询和分析功能,本质上来说,并非传统数据库所提供的存储、查询、分析功能。Hive..._hive应用场景

zblog采集-织梦全自动采集插件-织梦免费采集插件_zblog 网页采集插件-程序员宅基地

文章浏览阅读496次。Zblog是由Zblog开发团队开发的一款小巧而强大的基于Asp和PHP平台的开源程序,但是插件市场上的Zblog采集插件,没有一款能打的,要么就是没有SEO文章内容处理,要么就是功能单一。很少有适合SEO站长的Zblog采集。人们都知道Zblog采集接口都是对Zblog采集不熟悉的人做的,很多人采取模拟登陆的方法进行发布文章,也有很多人直接操作数据库发布文章,然而这些都或多或少的产生各种问题,发布速度慢、文章内容未经严格过滤,导致安全性问题、不能发Tag、不能自动创建分类等。但是使用Zblog采._zblog 网页采集插件

Flink学习四:提交Flink运行job_flink定时运行job-程序员宅基地

文章浏览阅读2.4k次,点赞2次,收藏2次。restUI页面提交1.1 添加上传jar包1.2 提交任务job1.3 查看提交的任务2. 命令行提交./flink-1.9.3/bin/flink run -c com.qu.wc.StreamWordCount -p 2 FlinkTutorial-1.0-SNAPSHOT.jar3. 命令行查看正在运行的job./flink-1.9.3/bin/flink list4. 命令行查看所有job./flink-1.9.3/bin/flink list --all._flink定时运行job

STM32-LED闪烁项目总结_嵌入式stm32闪烁led实验总结-程序员宅基地

文章浏览阅读1k次,点赞2次,收藏6次。这个项目是基于STM32的LED闪烁项目,主要目的是让学习者熟悉STM32的基本操作和编程方法。在这个项目中,我们将使用STM32作为控制器,通过对GPIO口的控制实现LED灯的闪烁。这个STM32 LED闪烁的项目是一个非常简单的入门项目,但它可以帮助学习者熟悉STM32的编程方法和GPIO口的使用。在这个项目中,我们通过对GPIO口的控制实现了LED灯的闪烁。LED闪烁是STM32入门课程的基础操作之一,它旨在教学生如何使用STM32开发板控制LED灯的闪烁。_嵌入式stm32闪烁led实验总结

Debezium安装部署和将服务托管到systemctl-程序员宅基地

文章浏览阅读63次。本文介绍了安装和部署Debezium的详细步骤,并演示了如何将Debezium服务托管到systemctl以进行方便的管理。本文将详细介绍如何安装和部署Debezium,并将其服务托管到systemctl。解压缩后,将得到一个名为"debezium"的目录,其中包含Debezium的二进制文件和其他必要的资源。注意替换"ExecStart"中的"/path/to/debezium"为实际的Debezium目录路径。接下来,需要下载Debezium的压缩包,并将其解压到所需的目录。

Android 控制屏幕唤醒常亮或熄灭_android实现拿起手机亮屏-程序员宅基地

文章浏览阅读4.4k次。需求:在诗词曲文项目中,诗词整篇朗读的时候,文章没有读完会因为屏幕熄灭停止朗读。要求:在文章没有朗读完毕之前屏幕常亮,读完以后屏幕常亮关闭;1.权限配置:设置电源管理的权限。

随便推点

目标检测简介-程序员宅基地

文章浏览阅读2.3k次。目标检测简介、评估标准、经典算法_目标检测

记SQL server安装后无法连接127.0.0.1解决方法_sqlserver 127 0 01 无法连接-程序员宅基地

文章浏览阅读6.3k次,点赞4次,收藏9次。实训时需要安装SQL server2008 R所以我上网上找了一个.exe 的安装包链接:https://pan.baidu.com/s/1_FkhB8XJy3Js_rFADhdtmA提取码:ztki注:解压后1.04G安装时Microsoft需下载.NET,更新安装后会自动安装如下:点击第一个傻瓜式安装,唯一注意的是在修改路径的时候如下不可修改:到安装实例的时候就可以修改啦数据..._sqlserver 127 0 01 无法连接

js 获取对象的所有key值,用来遍历_js 遍历对象的key-程序员宅基地

文章浏览阅读7.4k次。1. Object.keys(item); 获取到了key之后就可以遍历的时候直接使用这个进行遍历所有的key跟valuevar infoItem={ name:'xiaowu', age:'18',}//的出来的keys就是[name,age]var keys=Object.keys(infoItem);2. 通常用于以下实力中 <div *ngFor="let item of keys"> <div>{{item}}.._js 遍历对象的key

粒子群算法(PSO)求解路径规划_粒子群算法路径规划-程序员宅基地

文章浏览阅读2.2w次,点赞51次,收藏310次。粒子群算法求解路径规划路径规划问题描述    给定环境信息,如果该环境内有障碍物,寻求起始点到目标点的最短路径, 并且路径不能与障碍物相交,如图 1.1.1 所示。1.2 粒子群算法求解1.2.1 求解思路    粒子群优化算法(PSO),粒子群中的每一个粒子都代表一个问题的可能解, 通过粒子个体的简单行为,群体内的信息交互实现问题求解的智能性。    在路径规划中,我们将每一条路径规划为一个粒子,每个粒子群群有 n 个粒 子,即有 n 条路径,同时,每个粒子又有 m 个染色体,即中间过渡点的_粒子群算法路径规划

量化评价:稳健的业绩评价指标_rar 海龟-程序员宅基地

文章浏览阅读353次。所谓稳健的评估指标,是指在评估的过程中数据的轻微变化并不会显著的影响一个统计指标。而不稳健的评估指标则相反,在对交易系统进行回测时,参数值的轻微变化会带来不稳健指标的大幅变化。对于不稳健的评估指标,任何对数据有影响的因素都会对测试结果产生过大的影响,这很容易导致数据过拟合。_rar 海龟

IAP在ARM Cortex-M3微控制器实现原理_value line devices connectivity line devices-程序员宅基地

文章浏览阅读607次,点赞2次,收藏7次。–基于STM32F103ZET6的UART通讯实现一、什么是IAP,为什么要IAPIAP即为In Application Programming(在应用中编程),一般情况下,以STM32F10x系列芯片为主控制器的设备在出厂时就已经使用J-Link仿真器将应用代码烧录了,如果在设备使用过程中需要进行应用代码的更换、升级等操作的话,则可能需要将设备返回原厂并拆解出来再使用J-Link重新烧录代码,这就增加了很多不必要的麻烦。站在用户的角度来说,就是能让用户自己来更换设备里边的代码程序而厂家这边只需要提供给_value line devices connectivity line devices