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

智能推荐

Netty学习笔记五:Netty源码分析_netty 源码学习-程序员宅基地

文章浏览阅读322次。Netty学习笔记五:Netty源码分析EventLoop和EventLoopGroup线程模型高性能RPC框架3个要素一、IO模型(五种IO模型)二、数据协议(http/protobuf/Thrift)三、线程模型(主从线程组模型)EventLoopEventLoop好比一个线程,1个EventLoop可以服务多个Channel,一个Channel只有一个EventL..._netty 源码学习

Kyligence 发布数据和分析领域垂直大模型司南(Compass)_司南模型怎么测试-程序员宅基地

文章浏览阅读140次。12 月 19 日,跬智信息(Kyligence)正式发布数据和分析领域垂直大模型司南(Compass)(以下简称“司南大模型”)。基于多年数据和分析领域的实践积累和全行业指标洞察的海量语料,Kyligence司南大模型已具备自然语言对话分析、指标搜索与推荐、自动化数据洞察、KPI 评估、智能决策建议等核心能力。_司南模型怎么测试

MySQL数据库Insert语句慢SQL处理-程序员宅基地

文章浏览阅读3.8k次。#问题描述insert into …普通的插入语句,经常出现耗时2s以上#数据状态1.表数据量大,每天产生200万条数据2.高并发插入#问题解决1.由于表中数据量庞大,建议数据归档处理,冷热处理2.表中有过多索引,当数据insert时,索引会重排产生太多的io操作。导致缓慢,有必然要的只保留主键。3.表的数据库引擎,默认InnerDB,若数据不重要,可以使用MyISAM......

EasyDarwin开源流媒体云平台之EasyRMS录播服务器功能设计_开源录播系统-程序员宅基地

文章浏览阅读3.6k次。需求背景EasyDarwin开发团队维护EasyDarwin开源流媒体服务器也已经很多年了,之前也陆陆续续尝试过很多种服务端录像的方案,有:在EasyDarwin中直接解析收到的RTP包,重新组包录像;也有:在EasyDarwin中新增一个RecordModule,再以RTSPClient的方式请求127.0.0.1自己的直播流录像,但这些始终都没有成气候;我们的想法是能够让整套EasyDarwin_开源录播系统

oracle Plsql 执行update或者delete时卡死问题解决办法_oracle delete update 锁表问题-程序员宅基地

文章浏览阅读1.1w次。今天碰到一个执行语句等了半天没有执行:delete table XXX where ......,但是在select 的时候没问题。后来发现是在执行select * from XXX for update 的时候没有commit,oracle将该记录锁住了。可以通过以下办法解决: 先查询锁定记录 Sql代码 SELECT s.sid, s.seri_oracle delete update 锁表问题

Xcode Undefined symbols 错误_xcode undefined symbols:-程序员宅基地

文章浏览阅读3.4k次。报错信息error:Undefined symbol: typeinfo for sdk::IConfigUndefined symbol: vtable for sdk::IConfig具体信息:Undefined symbols for architecture x86_64: "typeinfo for sdk::IConfig", referenced from: typeinfo for sdk::ConfigImpl in sdk.a(config_impl.o) _xcode undefined symbols:

随便推点

使用flex-wrap实现弹性盒自动换行-程序员宅基地

文章浏览阅读2w次,点赞6次,收藏10次。布局的时候,我们常常会需要一行排列3/4/5/6个盒子,必要时自动换行,这时可以借助CSS3中的flex-wrap属性。flex-wrap: nowrap|wrap|wrap-reverse|initial|inherit;nowrap为默认值,wrap必要时实现自动换行,reverse必要时换行并反向排列关键是在父元素中设置flex-wrap值为wrap, 然后是设置子元素的wi...

改变Android Studio的背景background_as怎么设置背景-程序员宅基地

文章浏览阅读2.7k次,点赞2次,收藏5次。改变Android Studio的背景background我们先点File然后再点Settings里的Appearance,点击Theme换成Darcula 把白色换成黑色,这样的好处是换成background是图片比较清晰。此处正式开始AS换背景这里我们颜色从白色换成了黑色,先点File里Settings的Appearance然后点background image把你喜欢的图片放进去(图片放在D盘自己新建的文件)..._as怎么设置背景

桩筏有限元中的弹性板计算_专栏 l 增材制造点阵结构在压力容器优化设计中的应用...-程序员宅基地

文章浏览阅读179次。“增材制造是未来制造业的发展趋势,其优势显而易见,它可以实现传统加工工艺难以制造的设计,比如复杂薄壁结构、点阵结构、一体化结构等。其中,点阵结构作为一种新型的轻量化结构,具有良好的比刚度、比强度等力学性能。传统加工工艺很难制造点阵结构,3D打印技术的快速发展使得点阵结构的制造更加具有可行性。”本期谷.专栏列举了面向增材制造的点阵加筋一体化压力容器的设计与分析案例,仿真技术作为正向设计体系..._点阵结构的等效属性计算

Firefox安装广告屏蔽插件(uBlock Origin)_ublock origin插件-程序员宅基地

文章浏览阅读5.9k次,点赞2次,收藏2次。由于国内用户IP被屏蔽的原因,安装广告屏蔽插件(uBlock Origin、AdGuard、AdBlocker、AdBlock For Firefox、AdBlock)访问受限,官方原因为“由于法律原因不可用(HTTP 451 Unavailable For Legal Reasons)”,需要另辟蹊径安装,以下是安装uBlock Origin的方法介绍。然后,在Firefox的扩展管理页面,打开【从文件安装附加组件】选项。选择刚才下载的.xpi文件,就可以成功安装了。_ublock origin插件

k8s挂载目录_kubernetes(k8s)的pod使用统一的配置文件configmap挂载-程序员宅基地

文章浏览阅读1.2k次。在容器化应用中,每个环境都要独立的打一个镜像再给镜像一个特有的tag,这很麻烦,这就要用到k8s原生的配置中心configMap就是用解决这个问题的。使用configMap部署应用。这里使用nginx来做示例,简单粗暴。直接用vim常见nginx的配置文件,用命令导入进去kubectl create cm nginx.conf --from-file=/home/nginx.conf然后查看kub..._pod mount目录会自动创建吗

java计算机毕业设计springcloud+vue基于微服务的分布式新生报到系统_关于spring cloud的参考文献有啥-程序员宅基地

文章浏览阅读169次。随着互联网技术的发发展,计算机技术广泛应用在人们的生活中,逐渐成为日常工作、生活不可或缺的工具,高校各种管理系统层出不穷。高校作为学习知识和技术的高等学府,信息技术更加的成熟,为新生报到管理开发必要的系统,能够有效的提升管理效率。一直以来,新生报到一直没有进行系统化的管理,学生无法准确查询学院信息,高校也无法记录新生报名情况,由此提出开发基于微服务的分布式新生报到系统,管理报名信息,学生可以在线查询报名状态,节省时间,提高效率。_关于spring cloud的参考文献有啥