使MySQL引擎使用索引避免全表扫描的sql查询优化

使用MySQL进行千万级别数据查询的技巧 拿 limit 10000, 10 这条语句来说明一下, MySQL在执行这条查询的时候,需要查询 10010 (10000 + 10) 条记录,然后只返回最后 10 条,并将前面的 10000 条记录抛弃,这样当翻页越靠后时,代价就变得越来越高。这是因为查询MySQL是跳过 OFFSET 行,而是取 OFFSET+N 行,然后放弃前 OFFSET 行,最后返回 N 行,当 OFFSET 特别大的时候,效率就非常的低下。先在索引树中找到开始位置的 id 值,再根据找到的 id 值查询行数据。 阅读详情

本文主要内容:

1:查询语句where 子句使用时候优化或者需要注意的

2:like语句使用时候需要注意

3:in语句代替语句

4:索引使用或是创建需要注意

假设用户表有一百万用户量。也就是1000000.num是主键

1:对查询进行优化,应尽量避免全表扫描,首先应考虑在where及order by 涉及的列上创建索引。

因为:索引对查询的速度有着至关重要的影响。

2:尽量避免在where字句中对字段进行null值的判断。否则将会导致引擎放弃使用索引而进行全表扫描。

例如:select id from user where num is null 。可以将num是这个字段设置默认值0.确保表中没有null值,然后在进行查询。

sql如下:select id from user where num=0;

(考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储100条记录。如果没有索引,查询将对整个表进行扫描,最坏的情况下,如果所有数据页都不在内存,需要读取10^4个页面,如果这10^4个页面在磁盘上随机分布,需要进行10^4次I/O,假设磁盘每次I/O时间为10ms(忽略数据传输时间),则总共需要100s(但实际上要好很多很多)。如果对之建立B-Tree索引,则只需要进行log100(10^6)=3次页面读取,最坏情况下耗时30ms。这就是索引带来的效果,很多时候,当你的应用程序进行SQL查询速度很慢时,应该想想是否可以建索引)

3:应尽量避免在where子句中使用!=或者是<>操作符号。否则引擎将放弃使用索引,进而进行全表扫描。

4:应尽量避免在where子句中使用or来连接条件,否则导致放弃使用索引而进行全表扫描。可以使用 union 或者是 union all代替。

例如: select id from user where num =10 or num =20 这个语句景导致引擎放弃num索引,而要全表扫描来进行处理的。

可以使用union 或者是 union all来代替。如下:

select id from user where num = 10;

union all

select id from user where num =20;

(union 和 nuion all 的区别这里就不赘述了)

5:in 和 not in 也要慎用,否则将会导致全表扫描。

in 对于连续的数组,可以使用between ...and.来代替。

例如:

select id from user where num in (1,2,3);

像这样连续的就可以使用between ...and...来代替了。如下:

select id from user where num between 1 and 3;

6:like使用需注意

下面这个查询也将导致全表查询:

select id from user where name like '%三';

如果想提高效率,可以考虑到全文检索。比如solr或是luncene

而下面这个查询却使用到了索引:

select id from user where name like '张%';

7:where子句参数使用时候需注意

如果在where子句中使用参数,也会导致全表扫描。因为sql只会在运行时才会解析局部变量。但优化程序不能将访问计划的选择推迟到运行时;必须在编译时候进行选择。然而,如果在编译时建立访问计划,变量的值还是未知大,因而无法作为索引选择输入项。

如下面的语句将会进行全表扫描:

select id from user where num = @num

进行优化,我们知道num就是主键。是索引。

所以可以改为强制查询使用索引:

select id from user where (index(索引名称)) where num = @num;

8:尽量避免在where子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。

例如:select id from user where num/2=100

应修改为:

select id from user where num = 100*2;

9:尽量避免爱where子句中对字段进行函数操作,这将导致引擎放弃索引,而进行全表扫描。

例如:

select id from user substring(name,1,3) = 'abc' ,这句sql的含义其实就是,查询name以abc开头的用户id

(注:substring(字段,start,end)这个是mysql的截取函数)

应修改为:

select id from user where name like 'abc%';

10:不要在where子句中的"="左边进行函数、算术运算或是使用其他表达式运算,否则系统可能无法正确使用索引

11:复合索引查询注意

在使用索引字段作为条件时候,如果该索引是复合索引,那么必须使用该索引中的第一个字段作为条件时候才能保证系统使用该所以,否则该索引将不会被使用,并且应尽可能的让字段顺序和索引顺序一致。

12:不要写一些没意义的查询。

例如:需要生成一个空表结构和user表结构一样(注:生成的新 new table的表结构和 老表 old table 结构一致)

select col1,col2,col3.....into newTable from user where 1=0

上面这行sql执行后不会返回任何的结果集,但是会消耗系统资源的。

应修改为:

create table newTable (....)这种语句。

13:很多时候用exists 代替 in是一个很好的选择。

比如:

select num from user where num in(select num from newTable);

可以使用下面语句代替:

select num from user  a where exists(select num from newTable b where b.num = a.num );

14:并不是所有索引对查询都有效,sql是根据表中数据进行查询优化的,当索引lie(索引字段)有大量重复数据的时候,sql查询可能不会去利用索引。如一表中字段 sex、male、female 几乎各一半。那么即使在sex上创建了索引对查询效率也起不了多大作用。

15:索引创建需注意

并非索引创建越多越好。索引固然可以提高相应的查询效率,但是同样会降低insert以及update的效率。因为在insert或是update的时候有可能会重建索引或是修改索引。所以索引怎样创建需要慎重考虑,视情况而定。一个表中所以数量最好不要超过6个。若太多,则需要考虑一些不常用的列上创建索引是否有必要。



作者:微信公众号_凯哥java
链接:https://www.jianshu.com/p/e77ef13be378
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

MySQL索引SQL优化一网打尽 学会了SQL怎么写,却优化?大量例子让你复习吃透这玩意!!! 阅读详情

相关推荐

偷偷告诉mysql这47个SQL性能优化技巧,赶紧收藏了!

然而,查询解析器认为这是两个同的SQL语句,要解析两次,生成两个同的执行计划,作为一名严谨的Java开发工程师,应该保证两个一样的SQL语句,管在任何地方都是一样的。新行标识所用的计数值重置为该列的种子。SQL执行计划是可以被重用的,SQL越简单,被重用的概率越大,生成执行计划也是很耗时的。Innodb是以聚集索引的顺序来存储的,对于Innodb来说,二级索引在叶子节点中所保存的是行的主键信息,如果是用二级索引查询数据的话,在查找到相应的键值后,还要通过主键进行二次查询才能获取我们真实所需要的数据。

力哥讲技术 2001

面试官:一千万的数据,你是怎么查询的?

上面模拟的是从1000W条数据表中 ,一次查询出100W条数据,看起来性能佳,但是我们常规业务中,很少有一次性从mysql查询出这么多条数据量的场景。先对查询的字段创建唯一索引 根据业务需求,先定位查询范围(对应主键id的范围,比如大于多少、小于多少、IN) 查询时,将第2步确定的范围作为查询条件。这种方法要求更高些,id必须是连续递增(注意是连续递增,仅仅是递增哦),而且还得计算id的范围,然后使用 between,sql如下。命中的索引一样,命中唯一索引查询,效率高出止十倍。

CXikun的博客 9686

MYSQL随机抽取查询 MySQL Order By Rand()效率问题

要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RAND() LIMIT 1。 但是,后来我查了一下MYSQL的官方手册,里面针对RAND()的提示大概意思就是,在ORDER BY从句里面使用RAND()函数,因为这样会导致数据列被多次扫描。但是在MYSQL 3.23版本中,仍然可以通过ORDER BY RAND()来实现随机。 但是真正测试一下才发现这样效率非常低。一个15万余条的库,查询5条数据,居然要8秒以上。查看官方手册,也说rand()放在ORDER BY 子句中会被执行多次,自然效率及很低。 代

SQL千万级大数据量查询优化

转发自:https://blog.csdn.net/long690276759/article/details/79571421?spm=1001.2014.3001.5506* (防止查询资料找到来源,很详细!!!支持原创,本人只是搬运工)

yanghao0571的博客 2976

千万级别数据查询优化mysql

首先建表 CREATE TABLE `student` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL COMMENT '姓名', `age` int(10) unsigned NOT NULL COMMENT '岁数', PRIMARY KEY (`id`), KEY `age` (`age`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 插入数据(时间可

laozengsky的博客 3239

JDBC读取数据优化-fetch size

最近由于业务上的需求,一张旧表结构中的数据,需要提取出来,根据规则,导入一张新表结构中,开发同学写了一个工具,用于实现新旧结构的transformation, 实现逻辑简单,就是使用jdbc从A表读出数据,做了一些处理,再存入新表B中,发现读取旧表的操作,非常缓慢,无法满足要求。 读取数据的示例代码, conn = getConnection(); long start = System.currentTimeMillis(); ps = conn.prepareStatement(sql); rs = p

qq_38649702的博客 3768

mysqlsql查询语句优化_Mysql实例SQL查询语句优化的实用方法总结

Mysql实例SQL查询语句优化的实用方法总结》要点:本文介绍了Mysql实例SQL查询语句优化的实用方法总结,希望对您有用。如果有疑问,可以联系我们。查询语句的优化SQL效率优化的一个方式,可以通过优化sql语句来尽量使用已有的索引,避免全表扫描,从而提高查询效率.最近在对项目中的一些sql进行优化,总结整理了一些方法.MYSQL实例1、在表中建立索引,优先考虑where、group by使...

weixin_32920055的博客 219

一个系列搞懂Mysql数据库12:从实践sql语句优化开始

Table of Contents 字段 索引 查询SQL 引擎 MyISAM InnoDB 0、自己写的海量数据sql优化实践 mysql百万级分页优化   普通分页    优化分页   总结 除非单表数据未来会一直断上涨,否则要一开始就考虑拆分,拆分会带来逻辑、部署、运维的各种复杂度,一般以整型值为主的表在千万级以下,字符串为主的表在五百万以下是没有太大问题的。而事实上很多时候MySQL单表的性能依然有优化空间,甚至能正常支撑千万级以上的数据量: 字段 尽量使用TINYINT

Viper的程序员修炼手册 1828

MySql Innodb存储引擎sql优化

现在,你可以去把那些慢查询按在地上摩擦了!小表 JOIN 大表。

fjkxyl的博客 1314

MySQL处理达到百万级数据时,如何优化

1.两种查询引擎查询速度(myIsam 引擎 ) InnoDB 中保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行。 MyISAM只要简单的读出保存好的行数即可。 注意的是,当count(*)语句包含 where条件时,两种表的操作有些同,InnoDB类型的表用count(*)或者count(主键),加上...

何以解忧 862

SQL 语句在 MySQL 中的执行过程

连接层:负责与客户端建立连接,接收客户端发送的 SQL 语句。服务层:包括查询缓存、解析器、预处理器、优化器等组件,负责对 SQL 语句进行解析、优化等操作。存储引擎层:负责实际的数据存储和检索,同的存储引擎具有同的特点和性能。文件系统层:存储数据文件和日志文件等。

SOS5418818845的博客 1068

MySQL SQL优化 实践笔记

1

qq_33500066的博客 191

JAVA面试题分享二百九十二:62条SQL优化策略

使用索引字段和 ORDER BY子句 LIMIT M,N 实际上可以减缓查询在某些情况下,有节制地使用,在 WHERE 子句中使用 UNION 代替子查询,在重新启动的 MySQL,记得来温暖你的数据库,以确保数据在内存和查询速度快,考虑持久连接,而是多个连接,以减少开销。基准查询,包括使用服务器上的负载,有时一个简单的查询可以影响其他查询,当负载增加在服务器上,使用 SHOW PROCESSLIST 查看慢的和有问题的查询,在开发环境中产生的镜像数据中测试的所有可疑的查询

之乎者也·的博客 1176

MySQL千万级数据查询优化技巧及思路

MySQL是一种流行的关系数据库,具有良好的可扩展性和高可用性。但是,在处理大量数据时,MySQL的性能可能会受到一些限制。在实际应用中,需要对MySQL进行优化,以提高其性能和可靠性。本文介绍了一些优化MySQL的技术和方法,包括数据库设计、SQL查询优化、硬件优化和其他优化技巧。通过合理的MySQL优化,可以提高MySQL查询速度和并发处理能力,从而提高应用程序的性能和可靠性。

Dark_orange的博客 6370

在一个千万级的数据库查寻中,如何提高查询效率?

1)数据库设计方面: a. 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 b. 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0 ...

heronsbill_peng 1025

千万级数据量的插入操作(MYSQL

前几天因为公司业务迁移需要,需要从数仓同步一张大表,数据总量大概三千多万,接近四千万的样子,当遇到这种数据量的时候,综合考虑之后,当前比较流行的框架都能满足于生产需求,使用框架对性能的损耗过于严重,所以有了以下千万级数据量的插入方案。 当数据量达到一定规模的时候,假设一个语句为这样,还比较小的,只有三个字段。 INSERT INTO user_operation_min_temp(obse...

张音乐的博客 3620

千万级数据表如何用索引快速查找?

千万级数据表如何用索引快速查找? 1.索引的本质解析 索引: 帮助 MySQL 高效获取数据的排好序的数据结构 索引数据结构: 二叉树、红黑树、Hash表、B-Tree 注: 查找一次经过一次I/O 二叉树:右边的子节点>父节点,左边的子节点<父节点 红黑树:二叉平衡树,会自旋,二叉树当索引结构并合适,I/O次数太多 B-Tree:当我们想减少I/O次数,那就得减少树的高度,但是数据量恒定的情况下,高度减少意味着宽度得增加,从而引入B树的概念。 B+Tree:(MySql数据库索引使用

糖哲睿的博客 1505

mysql千万级数据量查询优化参考 —— 筑梦之路

Mysql查询性能优化要从三个方面考虑,库表结构优化索引优化查询优化

筑梦之路 3749
上一篇: Eclipse创建Maven多模块工程
下一篇: 千万级数据量怎么做分页查询
zhifeng687
zhifeng687 领域专家: 前端开发技术领域 领域专家: 前端开发技术领域
博客等级 码龄12年 1317粉丝 280原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值