Mysql多表关联不走索引的原因
刚入职第一天,有个大佬写了一个统计函数count(*)需要对两张表a,b做统计。咋一看挺简单的,可是表a有1000万条数据,表b有300万条数据。使用LEFT JOIN进行查询。结果,一直查询不出来,可能时间就很久了。然后,这个锅就甩给第一天入职的我(我???)。
接下来,就研究一下如何对海量数据的查询进行优化。
一、准备过程
1.创建两张表,表A large_student_tb(幼儿园大班学生哈哈):1000万条。表B samll_student_tb(小班学生orzzzzzzz):300万条。不建立索引的情况。
a,建立存储过程:插入1000万条数据。n=10000000+1//为结束判断条件
-- 创建存储过程DROP PROCEDURE IF EXISTS my_insert;
CREATE PROCEDURE my_insert()
BEGINDECLARE n int DEFAULT 1;loopname:LOOPINSERT INTO `large_student_tb`(`id`,`username`,`password`) VALUES ( n,CONCAT('myname',n),CONCAT('password',n));SET n=n+1;IF n=1000000+1 THENLEAVE loopname;END IF;END LOOP loopname;
END;-- 执行存储过程
CALL my_insert();-- 数据插入成功后修改表模式InnoDB 时间稍微久点alter table `large_student_tb` engine=InnoDB;
鹅,确实很慢了。跑了1000s还没有跑完
继续让它跑一下吧。
笑了,这么久跑完了。可怜的电脑~~
b.查询一下条数
SELECT COUNT(*) FROM LARGE_STUDENT_TB
??懵了,是100万条??我少写了一个零。
为了科学的严谨。我还得再跑900万条。1万s??
先记录一下,100w条:
查所有:1.3s~1.5s。
查某条 username999999:0.6s
继续插入表剩下的900万条。。来把英雄联盟吧哈哈哈哈
还是先查询一下如何进行表的迁移吧。因为预期想来,1000万的表,加入索引,会加快查询速度和聚簇函数的计算速度。从而进行优化。但是我之前在办公室试过,往一张1000万的表里面加索引,速度很慢很慢,第一个想法是先建立一个一样的表,先加上索引,再进行表的迁移。相关操作如下
1.表的迁移:
insert into db1.table1 select * from db2.table2 #完全复制
-- 创建存储过程DROP PROCEDURE IF EXISTS my_insert;
CREATE PROCEDURE my_insert()
BEGINDECLARE n int DEFAULT 1000000+1;loopname:LOOPINSERT INTO `large_student_tb`(`id`,`username`,`password`) VALUES ( n,CONCAT('myname',n),CONCAT('password',n));SET n=n+1;IF n=10000000+1 THENLEAVE loopname;END IF;END LOOP loopname;
END;-- 执行存储过程
CALL my_insert();-- 数据插入成功后修改表模式InnoDB 时间稍微久点alter table `large_student_tb` engine=InnoDB;
二、比较
1.对增加了索引和没有索引的效果。查询速度是指数级别的增加,如下
SELECT * FROM LARGE_STUDENT_TB a where a.username = 'myname1002554'
-- index before 5.532s --index after 0.037s
我查询 username。没有对username增加索引的时候,需要5s才能从千万数据级别中查出某一条数据,增加了username字段为索引,秒查询。
2.索引增加后所占据的空间大小,以及表本身的空间大小
1.查询表的大小
select concat(round(sum(DATA_LENGTH/1024/1024),2),'MB') as data from TABLES where table_schema='simonsdb' and table_name='large_student_tb';
550.00MB
2.查询该索引的大小
SELECT CONCAT(ROUND(SUM(index_length)/(1024*1024), 2), ' MB') AS 'Total Index Size' FROM TABLES WHERE table_schema = 'simonsdb'
and table_name='large_student_tb'235.94MB
如上,索引的增加会带来存储空间的增加。但是速度却是很快。以牺牲空间换取这么大倍数的时间效率,值得。
3.多表连接查询的比较
-- 两表联查
EXPLAIN SELECT * FROM small_student_tb a left join large_student_tb b on a.username = 'myname1002554'
---这个查询不出来,有索引也没有用。待优化
SELECT * FROM small_student_tb a left join small_student_tb b on a.username = b.username;
--这个可以查询出来,用时间55s左右,需要优化
3.1 多表查询没有用上索引的原因。 如上3所显示,有个多表查询。我们需要用EXPLAIN关键字来排查原因。
1.单表可快速查询EXPLAIN
EXPLAIN SELECT * FROM LARGE_STUDENT_TB a where a.username = 'myname1002554'
2.两表连接查询ON。可以查出来,但是速度很慢55s。EXPLAIN一下
EXPLAIN SELECT * FROM small_student_tb a left join small_student_tb b on a.username = b.username
我们可以看到表a 也就是 small_student_tb在possible_keys中,没有用上索引。是什么原因导致它没有用上索引。会不会用上了以后就变快了?
综合比较,得出的结论是,左连接会做全盘扫描。类型为ALL,自然就不能使用索引了。因为左表a要全部扫描一遍。
3.查询不出来的语句。
EXPLAIN SELECT * FROM small_student_tb a left join large_student_tb b on a.username = 'myname1002554'
三、千万级别的数据查询个人优化建议
1.加索引。千万级别数据查询需要增加索引,索引在数据越多的情况下,效率越加明显
2.单独查表。两张千万级别的表查询,不建议用联表查。查一张结果,输出一个数据。去查询另外一张。
3.实在需要多表联查,应该注意两张表的字符编码级别是否相同。
四、MYSQL多表查询的区别
1.笛卡尔积:CROSS JOIN
笛卡尔积就是将A表的每一条记录与B表的每一条记录强行拼在一起。所以,如果A表有n条记录,B表有m条记录,笛卡尔积产生的结果就会产生n*m条记录。下面的例子,t_blog有10条记录,t_type有5条记录,所有他们俩的笛卡尔积有50条记
2.内连接INNER JOIN
内连接INNER JOIN是最常用的连接操作。从数学的角度讲就是求两个表的交集,从笛卡尔积的角度讲就是从笛卡尔积中挑出ON子句条件成立的记录。有INNER JOIN,WHERE(等值连接)
SELECT * FROM t_blog INNER JOIN t_type ON t_blog.typeId=t_type.id;
SELECT * FROM t_blog,t_type WHERE t_blog.typeId=t_type.id;
3.左连接LEFT JOIN
左连接LEFT JOIN的含义就是求两个表的交集外加左表剩下的数据。依旧从笛卡尔积的角度讲,就是先从笛卡尔积中挑出ON子句条件成立的记录,然后加上左表中剩余的记录(见最后三条)。
SELECT * FROM t_blog LEFT JOIN t_type ON t_blog.typeId=t_type.id;
左边的表格t_blog会全部输出来,右边的表格,没有的数据会为NULL
4.右连接RIGHT JOIN
同理右连接RIGHT JOIN就是求两个表的交集外加右表剩下的数据。
5.外连接:OUTER JOIN
外连接就是求两个集合的并集。从笛卡尔积的角度讲就是从笛卡尔积中挑出ON子句条件成立的记录,然后加上左表中剩余的记录,最后加上右表中剩余的记录。另外MySQL不支持OUTER JOIN,但是我们可以对左连接和右连接的结果做UNION操作来实现。
Mysql多表关联不走索引的原因相关推荐
- mysql join 组合索引_详解MySQL两表关联的连接表创建单列索引还是组合索引最优...
概述 今天主要介绍一下MySQL中两表关联的连接表是如何创建索引的相关内容,下面来看看详细的介绍. MySQL两表关联的连接表创建索引 创建数据库的索引,可以选择单列索引,也可以选择创建组合索引. 假 ...
- mysql表关联的索引命中失败 range checked for each record
mysql表关联的索引命中失败和由此带来的思考 ###问题描述 最近翻了慢查询日志,大多数都是备份,夜晚的临时查询表生成,但是偶尔有几句是早年间留下的legend code留下的错误.有几个显示的问题 ...
- 数据查询必备技能SQL调优:Mysql什么情况下不走索引
背景分析 今天领导在查询报表时,发现特别慢,于是引发一系列关于sql优化的工作,最终发现是分析同学在进行多表关联时进行不等值关联造成全表扫描,且使用字段无索引造成1W条数据表和20W数据表关联时执行缓 ...
- MySQL多表关联查询效率高点还是多次单表查询效率高,为什么?
这里写目录标题 MySQL多表关联查询对比多次单表查询,哪个效率高? 疑问: 高手解答: <阿里巴巴JAVA开发手册>里面写超过三张表禁止join 这是为什么?这样的话那sql要怎么写? ...
- oracle 不走索引的原因
oracle 不走索引的原因 2013-02-01 13:46 9098人阅读 评论(0) 收藏 举报 分类: oracle(27) create table tb2 as select ...
- MySQL回表与覆盖索引
MySQL回表与覆盖索引 1. MySQL存储引擎 2. MySQL索引结构 2.1 B树和B+树定义 2.2 B树和B+树区别 2.3 B+Tree优点 3. MySQL索引回表 4. MySQL覆 ...
- oracle表关联为什么不走索引,Oracle执行计划不走索引的原因总结
51Testing软件测试网\2cGa+\2o 在操作中,为什么有时一个表的某个字段明明有索引,当观察一些语的执行计划确不走索引呢?如何解决呢?本文我们主要就介绍这部分内容,接下来就让我们一起来了解一 ...
- Mysql优化,导致查询不走索引的原因总结
原文地址:http://blog.csdn.net/m0_37808356/article/details/72526687 最近公司让我做SQL优化的工作(MySql),用explain发了一些问题 ...
- mysql看表关联视图_MySQL数据库 : 自关联,视图,事物,索引
自关联查询(自身id关联自身id(主键),查询的时候可以逻辑分为两个表,然后分别起一个别名来区分) select * from areas as city inner join areas as pr ...
最新文章
- 特征描述子提取公用接口
- jQuery选择器整理
- java遍历对象属性_java开发中遍历一个对象的所有属性并set值 缓存优化
- 用Socket 打造跨语言跨操作系统的网络MORPG游戏(三)
- 【题目解析】1015 Reversible Primes (20 分)_27行代码AC
- 2021牛客暑期多校训练营5 E-Eert Esiwtib(树形dp+位运算)
- PHP笔记-Smarty模板引擎的使用
- 信息学奥赛一本通 1061:求整数的和与均值 | OpenJudge NOI 1.5 04
- docker下的mysql my.ini_docker部署mysql启动失败
- Proxmark3教程1:小白如何用PM3破解复制M1全加密门禁IC卡
- IPD与项目管理、CMM的关系
- MATLAB矩阵计算大全
- c++使用libiconv
- 【opencv之Roberts算子】
- 算法设计与分析 —— 排列问题
- Labview温度采集系统
- 世达03017数字万用表的使用
- 留学生如何搞定Extended Essay?
- jemalloc 内存分配器 是什么
- BZOJ 1140 POI2009 KOD 编码 DFS
热门文章
- 东南大学计算机数学专业,东南大学数学系
- [BZOJ 3033] 太鼓达人
- VUE+Express+MongoDB前后端分离,实现一个便签墙(一)
- |夹逼准则 单调有界准则捷径|day9
- spring声明式事务 同一类内方法调用事务失效
- 深发展,或有可能的投机机会
- 在Unity中实现音口同步-01-概述
- 关于thymeleaf的#strings.abbreivate(str,10)
- 如何linux搭建vpn服务器
- java excel打印_Java如何设置电子表格的打印区域?