爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      MySQL 索引与性能调优

      首页 知识中心 数据库 文章详情页

      MySQL 索引与性能调优

      2023-05-15 09:59:41 阅读次数:119

      MySQL,索引

      索引用于快速找出在某个列中有一特定值的行,如果不使用索引MySQL必须从第l条记录开始读完整个表,直到找出相关的行.表越大,查询数据所花费的时间越多,如果表中查询的列有一个索引,MySQL能快速到达某个位置去搜寻数据文件,而不必查看所有数据,可加快数据查询的查询速度提高效率,索引可在创建表时增加,也可动态调整已有表

      通俗的来说索引是一种数据结构,是帮助MySQL进行高效检索数据的一种机制,你可以简单理解为排好序的快速查找数据结构,

      索引都是B+树(多路搜索树)结构组织的索引,包括聚集索引,复合索引,前缀索引,唯一索引,都是b+树索引.

      优势:1.提高数据检索效率,降低数据库IO成本,降低CPU消耗。
      劣势: 2.索引是一张表,索引也占空间,虽然提高了查询速度,但也会降低表的更新速度,如果新加数据,索引也会自动更新。

      CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据时。
      IO磁盘平静,服务器硬件平静。

      创建普通索引: 在创建表时指定索引类型,如下在u_id字段添加一个普通索引,该索引作用只是加对快数据的访问速度.

      MariaDB [lyshark]> create table book
          -> (
          -> u_id int not null,
          -> u_book varchar(20) not null,
          -> index(u_id)
          -> );
      
      -- 使用show index语句查看指定表中创建的索引
      MariaDB [lyshark]> show index from book;
      MariaDB [lyshark]> show create table book \G;
      MariaDB [lyshark]> explain select * from book where u_id=1 \G;
      

      创建唯一索引: 创建唯一索引的主要原因是减少查询索引列操作的执行时间,尤其是对比较庞大的数据表.它与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值.如果是组合索引,则列值的组合必须唯一.

      MariaDB [lyshark]> create table table_1
          -> (
          -> id int not null,
          -> name char(30) not null,
          -> unique index UniqIdx(id)
          -> );
      Query OK, 0 rows affected (0.02 sec)
      
      MariaDB [lyshark]> show create table table_1 \G;
      *************************** 1. row ***************************
             Table: table_1
      Create Table: CREATE TABLE `table_1` (
        `id` int(11) NOT NULL,
        `name` char(30) NOT NULL,
        UNIQUE KEY `UniqIdx` (`id`)             #id字段已经成功建立了一个名为UniqIdx的唯一索引
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1
      1 row in set (0.00 sec)
      

      创建单列索引: 单列索引是在数据表中的某一个字段上创建的索引,一个表中可以创建多个单列索引.前面两个例子中创建的索引都为单列索引.

      MariaDB [lyshark]> create table table_2
          -> (
          -> id int not null,
          -> name char(50) null,
          -> index SingleIdx(name(20))
          -> );
      Query OK, 0 rows affected (0.03 sec)
       
      MariaDB [lyshark]> show create table table_2 \G;
      *************************** 1. row ***************************
             Table: table_2
      Create Table: CREATE TABLE `table_2` (
        `id` int(11) NOT NULL,
        `name` char(50) DEFAULT NULL,
        KEY `SingleIdx` (`name`(20))          #name字段上已经成功建立了一个单列索引,名称为SingleIdx
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1
      1 row in set (0.00 sec)
      

      创建组合索引: 组合索引就是在多个字段上创建多个索引.

      MariaDB [lyshark]> create table table_3
          -> (
          -> id int not null,
          -> name char(30) not null,
          -> age int not null,
          -> info varchar(255),
          -> index MultiIdx(id,name,age)
          -> );
      

      创建全文索引: 全文索引可以用于全文搜索,全文索引适合用于大型数据集,目前只有MyISAM存储引擎支持FULLTEXT索引,并且只为CHAR、VARCHAR和TEXT列创建索引.索引总是对整个列进行,不支持局部(前缀)索引.

      -- 注意:MySQL5.7默认存储引擎室是InnoDB,在这里我们要改成MyISAM,不然索引会报错
      MariaDB [lyshark]> create table table_4(
          -> id int not null,
          -> name char(40) not null,
          -> age int not null,
          -> info varchar(255),
          -> fulltext index FullTxtIdx(info)
          -> )engine=MyISAM;
      

      创建空间索引: 空间索引必须在MyISAM类型的表中创建,且空间类型的字段必须为空,可以看到,table_5表的g字段上创建了名称为spatIdex的空间索引,注意:创建时间指定空间类型字段值的非空约束,并且表的存储引擎必须为MyISAM.

      MariaDB [lyshark]> create table table_5
          -> (
          -> g geometry not null,
          -> spatial index spatIdx(g)
          -> )engine=MyISAM;
      

      添加索引: 上面的几种形式都是在新建表中添加索引,如果需要在已存在表中添加则需要使用以下命令了.

      MariaDB [lyshark]> create table book
          -> (
          -> bookid int not null,
          -> bookname varchar(255) not null,
          -> authors varchar(255) not null,
          -> info varchar(255) null,
          -> comment varchar(255) null,
          -> year_public year not null
          -> );
      
      -- 添加普通索引
      MariaDB [lyshark]> alter table book add index BKNameIdx(bookname(30));
      
      -- 添加唯一索引
      MariaDB [lyshark]> alter table book add unique index UniqidIdx(bookId);
      
      -- 添加单列索引
      MariaDB [lyshark]> alter table book add index BkcmtIdx(comment(50));
      
      -- 添加组合索引
      MariaDB [lyshark]> alter table book add index BkAuAndInfoIdx(authors(30),info(50));
      
      -- 通过索引名字删除索引
      MariaDB [lyshark]> alter table book drop index UniqidIdx;
      MariaDB [lyshark]> alter table book drop index BKNameIdx;
      

      explain 字段的情况:

      MariaDB [lyshark]> explain select s_name,s_city from suppliers where s_id IN (select Gid from lyshark where Uid='a1');
      +------+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
      | id   | select_type | table     | type  | possible_keys | key     | key_len | ref   | rows | Extra |
      +------+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
      |    1 | PRIMARY     | lyshark   | const | PRIMARY       | PRIMARY | 30      | const |    1 |       |
      |    1 | PRIMARY     | suppliers | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
      +------+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
      
      MariaDB [lyshark]> explain select Course.CID,Course.Cname from Course join(
      select CID from lyshark.StudentScore where SID = (select SID from lyshark.Student where Sname='周梅')
      )as StudentScore on Course.CID = StudentScore.CID;
      +---------+-------------+--------------+------+---------------+------+---------+------+------+----------+
      | id      | select_type | table        | type | possible_keys | key     | key_len | ref  | rows | Extra |
      +---------+-------------+--------------+------+---------------+------+---------+------+------+----------+
      |    1(1) | SIMPLE      | Course       | ALL  | NULL          | NULL | NULL    | NULL |    3 |          |
      |    1(2) | SIMPLE      | StudentScore | ALL  | NULL          | NULL | NULL    | NULL |   18 |          |
      |    3    | SUBQUERY    | Student      | ALL  | NULL          | NULL | NULL    | NULL |   10 |          |
      +---------+-------------+--------------+------+---------------+------+---------+------+------+----------+
      
      ID字段的理解:
      1.当ID字段相同的情况下执行数据是从上到下,例如第一张表中会由上至下执行下来.
      2.当ID不同的情况,如果是子查询,id越大的将在最前面被执行,例如第二张表执行顺序为3->1(1)->1(2)
      

      select_type

      MariaDB [lyshark]> explain select * from tbl_emp a left join tbl_dept b on a.deptld=b.id where b.id is null
          -> union
          -> select * from tbl_emp a right join tbl_dept b on a.deptld = b.id where a.deptld is null;
      +------+--------------+------------+--------+---------------+---------+---------+------------------+------+---------+
      | id   | select_type  | table      | type   | possible_keys | key     | key_len | ref              | rows | Extra   |
      +------+--------------+------------+--------+---------------+---------+---------+------------------+------+---------+
      |    1 | PRIMARY      | a          | ALL    | NULL          | NULL    | NULL    | NULL             |    8 |         |
      |    1 | PRIMARY      | b          | eq_ref | PRIMARY       | PRIMARY | 4       | lyshark.a.deptld |    1 |         |
      |    2 | UNION        | b          | ALL    | NULL          | NULL    | NULL    | NULL             |    5 |         |
      |    2 | UNION        | a          | ALL    | fk_dept_id    | NULL    | NULL    | NULL             |    8 |         |
      | NULL | UNION RESULT | <union1,2> | ALL    | NULL          | NULL    | NULL    | NULL             | NULL |         |
      +------+--------------+------------+--------+---------------+---------+---------+------------------+------+---------+
      
      SIMPLE       => 标志着简单的select查询请求,查询中不包含子查询或者union查询.
      PRIMARY      => 查询中任何复杂的查询中,最外层的查询语句,就是最后加载的语句.
      SUBQUERY     => 子查询类型,在select或where列表中包含了子查询.
      DERIVED      => 在FROM列表中包含子查询,会被标记为DERIVED(衍生),此时会递归执行子查询,并存储在临时表中.
      UNION        => 若第二个SELECT出现在UNION之后,则标记为UNION.
      UNION RESULT => 从UNION表中获取结果的SELECT
      

      type 访问类型排列,只要能够达到ref,range级别就已经不错了,性能效率。

      system -> const -> eq_ref -> ref -> range ->index -> all
      
      
      system -> 表中只有一条记录,这是const类型的特里,平时不会出现。
      
      const  -> 主键唯一索引:表示通过索引一次就找到数据,例如查询一个常量。
      MariaDB [lyshark]> explain select * from lyshark where Uid="a1";
      +------+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
      | id   | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra |
      +------+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
      |    1 | SIMPLE      | lyshark | const | PRIMARY       | PRIMARY | 30      | const |    1 |       |
      +------+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
      
      
      eq_ref -> 唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配,常用于主键或唯一索引扫描。
      
      ref-> 非唯一性索引扫描,返回匹配某个单独值的所有行,被之上也是一种索引访问。查找扫描混合体
      
      MariaDB [lyshark]> create table t1(col1 int,col2 int);
      MariaDB [lyshark]> alter table t1 add index idx_col1_col2(col1,col2);
      MariaDB [lyshark]> explain select * from t1 where col1=1;
      +------+-------------+-------+------+---------------+---------------+---------+-------+------+--------+
      | id   | select_type | table | type | possible_keys | key           | key_len | ref   | rows | Extra  |
      +------+-------------+-------+------+---------------+---------------+---------+-------+------+--------+
      |    1 | SIMPLE      | t1    | ref  | idx_col1_col2 | idx_col1_col2 | 5       | const |    1 |        |
      +------+-------------+-------+------+---------------+---------------+---------+-------+------+--------+
      
      range -> 范围扫描,只检索给定范围的行,key列显示使用了那个索引。 where,between,<>,in 等查询中使用。
      
      explain select * from t1 where col1 between 1 and 2;
      explain select * from t1 where col1 in (1,2,3);
      
      index -> 全索引扫描,全表索引扫描,比all要好一些。
      MariaDB [lyshark]> explain select * from t1;
      
      all -> 全表扫描。最差的性能。
      

      possible_keys,key 是否使用到了索引,possible_keys 显示可能

      possible_keys => 显示可能应用在这张表中的索引,一个或多个,该索引会被列出,但不一定被实际查询使用。
      key => 实际应用到本次查询的索引类型。最重要的。如果为NULL,则说明没有使用索引。
      
      
      MariaDB [lyshark]> explain select col1,col2 from t1;
      +------+-------------+-------+-------+---------------+---------------+---------+------+------+-------+
      | id   | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra |
      +------+-------------+-------+-------+---------------+---------------+---------+------+------+-------+
      |    1 | SIMPLE      | t1    | index | NULL          | idx_col1_col2 | 10      | NULL |    1 |       |
      +------+-------------+-------+-------+---------------+---------------+---------+------+------+-------+
      
      
      ------------------------------------------------------------------------------
      查询中若使用了覆盖索引,则该索引仅出现key列表中 覆盖索引以下就是原理
      
      MariaDB [lyshark]> create table t1(col1 int,col2 int,col3 int);
      MariaDB [lyshark]> alter table t1 add index idx_col1_col2(col1,col2);
      
      -- 建立的索引与,查询的行数,必须一致,col1,col2是有索引的。
      MariaDB [lyshark]> explain select col1,col2 from t1;
      +------+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+
      | id   | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra   |
      +------+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+
      |    1 | SIMPLE      | t1    | index | NULL          | idx_col1_col2 | 10      | NULL |    1 | Using  |
      +------+-------------+-------+-------+---------------+---------------+---------+------+------+-------------+
      
      -- 扫描三个值,不会出现使用索引的情况。
      MariaDB [lyshark]> explain select col1,col2,col3 from t1;
      +------+-------------+-------+------+---------------+------+---------+------+------+-------+
      | id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
      +------+-------------+-------+------+---------------+------+---------+------+------+-------+
      |    1 | SIMPLE      | t1    | ALL  | NULL          | NULL | NULL    | NULL |    1 |       |
      +------+-------------+-------+------+---------------+------+---------+------+------+-------+
      

      possible_keys,key,ken_len

      key_len 表示索引中使用的字节数,这个长度用的越少越好,kenLen长度是根据表的定义计算得出,而不是表中数据检索出的。
      
      
      
      
      ref 显示索引的那一列被使用了,如果可能的话,是一个常数,那些列或常量被用于查找索引列上的值。定义了引用了那些库。
      
      rows 根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数,该值当然也是越小越好。 每张表有多少行被优化器查询。
      
      MariaDB [lyshark]> explain select * from lyshark;
      +------+-------------+---------+------+---------------+------+---------+------+------+-------+
      | id   | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra |
      +------+-------------+---------+------+---------------+------+---------+------+------+-------+
      |    1 | SIMPLE      | lyshark | ALL  | NULL          | NULL | NULL    | NULL |   17 |       |
      +------+-------------+---------+------+---------------+------+---------+------+------+-------+
      1 row in set (0.00 sec)
      
      
      MariaDB [lyshark]> create table tt1(id int primary key,col1 varchar(10),col2 varchar(10));
      MariaDB [lyshark]> create table tt2(id int primary key,col1 varchar(10),col2 varchar(10));
      MariaDB [lyshark]> create index idt_col1_col2 on tt2(col1,col2);
      
      MariaDB [lyshark]> explain select * from tt1,tt2 where tt1.id = tt2.id and tt2.col1 = 'admin';
      +------+-------------+-------+--------+-----------------------+---------+---------+----------------+------+-------------+
      | id   | select_type | table | type   | possible_keys         | key     | key_len | ref            | rows | Extra       |
      +------+-------------+-------+--------+-----------------------+---------+---------+----------------+------+-------------+
      |    1 | SIMPLE      | tt1   | ALL    | PRIMARY               | NULL    | NULL    | NULL           |    1 |             |
      |    1 | SIMPLE      | tt2   | eq_ref | PRIMARY,idt_col1_col2 | PRIMARY | 4       | lyshark.tt1.id |    1 | Using where |
      +------+-------------+-------+--------+-----------------------+---------+---------+----------------+------+-------------+
      2 rows in set (0.00 sec)
      

      extra 扩展列

      using filesort 产生了文件内排序,完蛋了,mysql无法使用索引进行排序,使用了外部的索引排序,而不是按照表内的索引顺序进行读取。mysql无法利用索引完成排序,操作成为文件排序。

      MariaDB [lyshark]> create table tab1(id int primary key,col1 int,col2 int,col3 int);
      MariaDB [lyshark]> insert into tab1 values(1,1,2,3),(2,4,5,6),(3,7,8,9);
      MariaDB [lyshark]> create index tab1_col1_col2_col3 on tab1(col1,col2,col3);
      
      MariaDB [lyshark]> explain select col1 from tab1 where col1 order by col3 \G
      *************************** 1. row ***************************
                 id: 1
        select_type: SIMPLE
              table: tab1
               type: index
      possible_keys: tab1_col1_col2_col3
                key: tab1_col1_col2_col3
            key_len: 15
                ref: NULL
               rows: 3
              Extra: Using where; Using index; Using filesort
      1 row in set (0.00 sec)
      
      MariaDB [lyshark]> explain select col1 from tab1 where col1 order by col2,col3 \G
      
      查询使用索引,没问题的,只是说,我们没有针对order by 建立排序索引,或者是建立了索引,你没用上!!
      
      
      以下我们加上全部索引字段,从此下面这条sql性能更高了。
      MariaDB [lyshark]> explain select col1 from tab1 where col1 order by col1,col2,col3 \G
      *************************** 1. row ***************************
                 id: 1
        select_type: SIMPLE
              table: tab1
               type: index
      possible_keys: tab1_col1_col2_col3
                key: tab1_col1_col2_col3
            key_len: 15
                ref: NULL
               rows: 3
              Extra: Using where; Using index
      1 row in set (0.00 sec)
      
      
      如果可以,尽快优化。
      

      using temporary 彻底完犊子,这个会新建了一个内部临时表,然后操作完后再把临时表删除,动作更凶险。

      使用临时表保存中间结果,mysql在对查询结果排序时使用临时表,常用于排序order by 和分组查询group by .

      MariaDB [lyshark]> explain select * from tab1 where col1 in(1,2,3) group by col2 \G
      *************************** 1. row ***************************
                 id: 1
        select_type: SIMPLE
              table: tab1
               type: index
      possible_keys: tab1_col1_col2_col3
                key: tab1_col1_col2_col3
            key_len: 15
                ref: NULL
               rows: 3
              Extra: Using where; Using index; Using temporary; Using filesort  彻底完犊子
      1 row in set (0.00 sec)
      
      解决办法,你给我建立的索引个数和顺序,一定要按顺序来。
      MariaDB [lyshark]> explain select * from tab1 where col1 in(1,2,3) group by col1,col2 \G
      *************************** 1. row ***************************
                 id: 1
        select_type: SIMPLE
              table: tab1
               type: index
      possible_keys: tab1_col1_col2_col3
                key: tab1_col1_col2_col3
            key_len: 15
                ref: NULL
               rows: 3
              Extra: Using where; Using index   解决了。
      1 row in set (0.00 sec)
      

      using index 这种情况是好事,表示相应的操作使用了 covering index 使用了覆盖索引,效率不错,。

      如果同时出现了using where 表示索引被用来执行索引键值的查找。

      如果没有同时出现using where 表明索引用来读取数据而非执行查找动作。

      MariaDB [lyshark]> explain select col1,col2 from tab1;
      +------+-------------+-------+-------+---------------+---------------------+---------+------+------+-------------+
      | id   | select_type | table | type  | possible_keys | key                 | key_len | ref  | rows | Extra       |
      +------+-------------+-------+-------+---------------+---------------------+---------+------+------+-------------+
      |    1 | SIMPLE      | tab1  | index | NULL          | tab1_col1_col2_col3 | 15      | NULL |    3 | Using index |  using 表明直接从索引上找到了数据。
      +------+-------------+-------+-------+---------------+---------------------+---------+------+------+-------------+
      1 row in set (0.00 sec)
      
      

      覆盖索引,就是说你建立的复合索引是 x,y,z 那么你在查询是应该要覆盖这些索引,这样才能让索引,发挥其最大的性能,否则索引等于白建立。

      覆盖索引,尽量不要写星号,这种低效率的查询。

      select * from lyshark where id=1;     -- 完蛋的。
      select x,y,z from lyshark wehre id =1;   -- 覆盖到主键上,查询效率提升很多。
      

      using where -> 使用了where using join buffer -> 用到了缓存buffer

      实现单表索引优化

      create table if not exists article(
      id int(10) unsigned not null primary key auto_increment,
      author_id int(10) unsigned not null,
      category_id int(10) unsigned not null,
      views int(10) unsigned not null,
      comments int(10) unsigned not null,
      title varbinary(255) not null,
      content text not null );
      
      insert into article(author_id,category_id,views,comments,title,content) values(1,1,1,1,'1','1'),(1,1,1,2,'1','1'),(2,2,2,2,'2','2'),(3,3,3,3,'3','3');
      
      
      MariaDB [lyshark]> explain select id,author_id from article where category_id=1 and comments>1 order by views desc limit 1;
      
      -- 创建复合索引 all 变为了range 只解决了全表扫描问题
      MariaDB [lyshark]> create index idx_article_ccv on article(category_id,comments,views);
      
      -- 最后一个完整版的
      MariaDB [lyshark]> drop index idx_article_ccv on article;
      MariaDB [lyshark]> create index idx_article_cv on article(category_id,views);
      

      实现两表索引优化

      create table class
      (
          id int(10) auto_increment,
          card int(10) not null,
          primary key(id)
      );
      create table book
      (
          bookid int(10) auto_increment,
          card int(10) not null,
          primary key(bookid)
      );
      
      MariaDB [lyshark]> insert into class(card) values(floor(1+(rand()*20)));  * 10
      MariaDB [lyshark]> insert into book(card) values(floor(1+(rand()*20)));  * 10
      MariaDB [lyshark]> select * from book inner join class on book.card = class.card;
      
      -- 左连接的特性是左表全都有,连接右表的部分
      -- 左右链接总有一张表是用来驱动的,左连接链接的是右表,如下左表class右表是book
      MariaDB [lyshark]> select * from class left join book on book.card = class.card;
      
      -- 左连接情况下,将索引建立在右表上面效率是最高的,如下右表是book
      MariaDB [lyshark]> alter table book add index left_index(card);
      
      -- 右链接,需要将索引加到左边表上,也就是加到class表的card字段上.
      MariaDB [lyshark]> show index from book;
      MariaDB [lyshark]> drop index left_index on book;
      
      MariaDB [lyshark]> select * from class right join book on book.card = class.card;
      MariaDB [lyshark]> alter table class add index right_index(card);
      

      三张表索引优化

      create table phone
      (
          phoneid int(10) auto_increment,
          card int(10) not null,
          primary key(phoneid)
      );
      
      MariaDB [lyshark]> insert into phone(card) values(floor(1+(rand()*20)));  * 10
      
      
      -- 最简单的链接查询
      MariaDB [lyshark]> select * from class inner join book on class.card=book.card inner join phone on book.card=phone.card;
      
      
      -- 左连接查询
      MariaDB [lyshark]> explain select * from class left join book on class.card=book.card left join phone on book.card=phone.card;
      
      alter table book add index book_left_index(card);
      alter table phone add index phone_left_index(card);
      
      -- join 语句优化建议
      
      -- 1. 尽可能减少join语句中的NestedLoop的循环次数: 永远用小结果集,驱动大的结果集.
      -- 2. 优先优化NestedLoop的内层循环
      -- 保证join语句中被驱动表上join条件字段已经被索引.
      
      -- 当无法保证被驱动表的join条件字段被索引且内存资源充足的前提下,不要太吝惜joinbuffer 的设置.
      -- 如果是三表,左查询,那么我们应该将索引,建立在左连接表中.
      
      
      -- 右连接查询
      MariaDB [lyshark]> explain select * from class right join book on class.card=book.card right join phone on book.card=phone.card;
      
      alter table book add index book_left_index(card);
      alter table phone add index phone_left_index(card);
      

      解决中文乱码问题:

      [root@localhost mysql]# cp -a /usr/share/mysql/my-huge.cnf /etc/my.cnf
      [root@localhost mysql]# vim /etc/my.cnf
      [client]
      default-character-set=utf8
      
      [mysqld]
      character_set_server=utf8
      character_set_client=utf8
      collation-server=utf8_general_ci
      
      [mysql]
      default-character-set=utf8
      
      -- 查询字符集编码
      MariaDB [lyshark]> select * from information_schema.character_sets;
      MariaDB [lyshark]> show character set like 'utf8%';
      MariaDB [lyshark]> show variables like 'character_set%';
      
      -- 设置全局字符集
      set global character_set_client=utf8;
      set global character_set_connection=utf8;
      set global character_set_database=utf8;
      set global character_set_results=utf8;
      set global character_set_server=utf8;
      
      -- 更新指定表为utf8格式
      MariaDB [lyshark]> alter database lyshark default character set utf8 collate utf8_general_ci;
      MariaDB [lyshark]> alter table lyshark.user convert to character set utf8 collate utf8_general_ci;
      
      -- 错误日志
      [root@localhost ~]# vim /etc/my.cnf
      
      [mysqld]
      log-error="/var/log/mariadb/mariadb.log"
      
      MariaDB [(none)]> show variables like 'log%';
      [root@localhost ~]# cat /var/log/mariadb/mariadb.log |head -n 10
      
      MariaDB [(none)]> flush logs;
      
      
      -- 二进制日志
      [root@localhost ~]# vim /etc/my.cnf
      
      [mysqld]
      log-bin="/tmp"              #设置开启日志,也可不指定日志保存位置
      expire_logs_days = 10       #设置日志自动清理天数
      max_binlog_size = 100M      #定义了单个文件的大小限制
      
      
      -- 删除日志
      MariaDB [(none)]> show binary logs;
      MariaDB [(none)]> purge master logs to "mariadb-bin.000001";
      MariaDB [(none)]> purge master logs before "20180101";
      
      [root@localhost ~]# mysqlbinlog mariadb-bin.000001
      
      
      
      
      
      -- 慢查询日志
      MariaDB [lyshark]> show variables like '%slow_query_log%';
      MariaDB [lyshark]> set global slow_query_log=1;
      
      MariaDB [lyshark]> show variables like '%long_query_time%';
      MariaDB [lyshark]> set global long_query_time=3;
      MariaDB [lyshark]> show global status like '%Slow_queries%';
      
      [root@localhost mysql]# cat /var/lib/mysql/localhost-slow.log
      [root@localhost ~]# vim /etc/my.cnf
      
      [mysqld]
      log-slow-queries="/var/lib/mysql/localhost-slow.log"
      long_query_time=10
      log_output=FILE
      
      
      
      -s 排序方式
      -c 访问次数
      -l 锁定时间
      -r 返回记录
      -t 查询时间
      -al 平均锁定时间
      -ar 平均返回记录数
      -at 平均查询时间
      -t 返回前面多少条记录
      -g 匹配正则
      
      -- 得到返回记录集最多的10个SQL
      [root@localhost mysql]# mysqldumpslow -s -r -t 10 /var/lib/mysql/localhost-slow.log
      
      -- 得到访问次数最多的10个SQL
      [root@localhost mysql]# mysqldumpslow -s -c -t 10 /var/lib/mysql/localhost-slow.log
      
      -- 得到按照时间排序的前十条里面含有左连接的查询语句.
      [root@localhost mysql]# mysqldumpslow -s -t -t 10 -g 'left join' /var/lib/mysql/localhost-slow.log
      
      show variables like 'profiling';
      set profiling=on;
      
      MariaDB [lyshark]> select * from tbl_emp;
      MariaDB [lyshark]> show profiles;   // 查询系统中执行的sql
      -- 查询3号记录中的问题,得到3号语句的查询生命周期。
      MariaDB [lyshark]> show profile cpu,block io for query 3;
      

      MySQL 索引与性能调优

      MySQL 索引与性能调优

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://my.oschina.net/lyshark/blog/5550647,作者:LyShark,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:【MySQL】—— 数据库操作基础 和 常用语法(DDL,DML,DQL,DCL)

      下一篇:MySQL 5.7以上版本中sys库的学习

      相关文章

      2025-05-19 09:05:01

      Navicat 连接MySQL 8.0.11 出现2059错误 解决

      Navicat 连接MySQL 8.0.11 出现2059错误 解决

      2025-05-19 09:05:01
      MySQL , Navicat , 解决 , 连接
      2025-05-19 09:04:38

      mysql只有在任务处于完成状态才能运行

      mysql只有在任务处于完成状态才能运行

      2025-05-19 09:04:38
      MySQL , 任务 , 数据库 , 查询 , 状态
      2025-05-16 09:15:24

      MySQL 表的内外连接

      MySQL 表的内外连接

      2025-05-16 09:15:24
      MySQL , 显示 , 连接
      2025-05-14 10:33:16

      30天拿下Rust之切片

      在Rust中,切片是一种非常重要的引用类型。它允许你安全地引用一段连续内存中的数据,而不需要拥有这些数据的所有权。切片不包含分配的内存空间,它仅仅是一个指向数据开始位置和长度的数据结构。

      2025-05-14 10:33:16
      amp , end , 切片 , 字符串 , 引用 , 索引 , 迭代
      2025-05-14 10:33:16

      30天拿下Rust之向量

      在Rust语言中,向量(Vector)是一种动态数组类型,可以存储相同类型的元素,并且可以在运行时改变大小。向量是Rust标准库中的一部分,位于std::vec模块中。

      2025-05-14 10:33:16
      Rust , 使用 , 元素 , 向量 , 方法 , 索引 , 迭代
      2025-05-14 10:03:13

      MySQL 索引优化以及慢查询优化

      MySQL 是一种广泛使用的关系型数据库管理系统,因其性能优异和使用便捷而备受欢迎。然而,随着数据量的增长和查询复杂度的增加,性能瓶颈也变得越来越明显。

      2025-05-14 10:03:13
      MySQL , 优化 , 使用 , 性能 , 数据库 , 查询 , 索引
      2025-05-14 10:03:13

      【MySQL】-数据库优化(索引)

      索引(index)是帮助数据库高效获取数据的数据结构

      2025-05-14 10:03:13
      index , Tree , 二叉 , 搜索 , 数据 , 索引 , 节点
      2025-05-14 10:02:48

      SQL Server 执行计划1--数据查询

      SQL语言(在SQL Server也叫做T-SQL)是一个解释性的语言(declarative language), 主要是描述的是人想要从数据库里获取数据的逻辑。但数据库接收到SQL语句后,会根据相关的统计信息制定自己的取数策略(执行计划)。

      2025-05-14 10:02:48
      Index , 查找 , 索引
      2025-05-14 09:51:21

      mysql数据库中decimal数据类型比较大小

      在MySQL中,DECIMAL数据类型用于存储精确的数值,它非常适合用于需要高精度计算的场景,如金融应用。当我们需要在MySQL数据库中比较DECIMAL类型数据的大小时,可以使用标准的比较运算符,如>, <, >=, <=, = 和 <>(或!=)。

      2025-05-14 09:51:21
      MySQL , SQL , 数据类型 , 查询 , 比较 , 示例
      2025-05-14 09:51:15

      mysql 语句如何优化

      MySQL语句的优化是一个复杂但重要的过程,因为它可以显著提高数据库的性能。

      2025-05-14 09:51:15
      JOIN , MySQL , 优化 , 使用 , 排序 , 查询 , 索引
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5241801

      查看更多

      最新文章

      Navicat 连接MySQL 8.0.11 出现2059错误 解决

      2025-05-19 09:05:01

      mysql只有在任务处于完成状态才能运行

      2025-05-19 09:04:38

      MySQL 表的内外连接

      2025-05-16 09:15:24

      30天拿下Rust之切片

      2025-05-14 10:33:16

      MySQL 索引优化以及慢查询优化

      2025-05-14 10:03:13

      【MySQL】-数据库优化(索引)

      2025-05-14 10:03:13

      查看更多

      热门文章

      Confluence 6 MySQL 输入你的数据库细节

      2023-04-27 08:03:27

      MySQL timestamp(3)问题

      2023-04-27 08:00:12

      正确理解Mysql的列索引和多列索引

      2023-05-12 07:20:42

      MySQL安全小技巧

      2023-05-06 10:22:49

      MySQL数据库的安装(安装以及简单数据库操作)

      2023-05-06 10:22:26

      MySQL的数据库database(二)

      2023-04-23 09:35:19

      查看更多

      热门标签

      数据库 mysql 字符串 数据结构 MySQL 算法 redis oracle java sql python 数据 索引 SQL 查询
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      oracle分区表介绍(含本地分区索引和全局分区索引介绍)

      MySQL的InnoDB 三种行锁,SQL 语句加了哪些锁?

      【实现检查库存、生成订单并存入MySQL数据库】

      MySQL、MSSQL、Oracel、PostgreSQL、Access数据库注入相关

      数据库索引(1)-基础

      MySQL第八课 Truncate的用法

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号