MYSQl 全表扫描以及查询性能

-- 本文章仅用于学习,记录

一. Mysql在一些情况下全表检索比索引查询更快:

1.表格数据很少,使用全表检索会比使用索引检索更快。一般当表格总数据小于10行并且数据行的长度非常小的时候会使用全表检索;
 
2.在ON或者WHERE中,没有使用索引列作为查询条件;
 
3.使用了索引列与一个常量进行比较,但是mysql发现该索引列覆盖的数据太大,反而全表检索更快(一般当索引列覆盖的数据大于全表数据的30%时,会触发mysql使用全表检索);
 
4.使用了一个覆盖了大部分数据的索引列与另外表的列进行关联查询,此时mysql会使用全表检索。
 
 

二. 可能造成mysql 全表扫描的原因/查询性能差:

 
01. 使用null做为判断条件
如:select store from flowers where name = null;
建议在设计字段时尽量将字段的默认值设为0,改为select account where nickname = 0;
 
02. 左模糊查询Like %XXX%
如:select store from flowers where name like ‘%XXX%’ 或者 select store from flowers where name like ‘%XXX’
建议使用select store from flowers where name like ‘XXX%’,如果必须要用到做查询,需要评估对当前表全表扫描造成的后果;
 
03. 使用or做为连接条件
如:select store from flowers where id = 1 or id = 2;
建议使用union all,改为 select store from flowers where id = 1 union all select store from flowers where id = 2;
 
04. 使用in时(not in)
很多时候用 exists 代替 in 是一个好的选择。
如:select store from flowers where id in (1,2,3)
如果是连续数据,可以改为select store where id between 1 and 3;当数据较少时也可以参考union用法;
或者:select store from flowers where id in (select store_id from stores where id = 3 ),可以改为select store from flowers where id exsits (select store_id from stores where id = 3)
not in 可以对应 not exists;
 
05.使用!=或<>时
建议使用 <,<=,=,>,>=,between等;
 
06.对字段有操作时也会引起权标索引
如select amount from  stores where salary * 0.8 = 1000 或者 select name from stores where sustring(title,1,3) = ‘daffodils’;
应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如: 
select id from t where num/2=100 
建议改为: ---> select id from t where num=100*2 
不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。 
 
07.使用count(*)时
如select count(*) from member 
建议改为:---> select count(1) from member;
 
08.使用参数做为查询条件时
如果在 where 子句中使用参数,也会导致全表扫描。
因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项
select id from t where num=@num
建议改为强制查询使用索引:--->  select id from t with(index(索引名)) where num=@num
 
 
09.使用手动创建的临时表
建议使用联合(UNION / UNION ALL)来代替手动创建的临时表
当我们可以确认不可能出现重复结果集或者不在乎重复结果集的时候尽量使用union all而不是union ,因为union 和union all 的差异主要是前者需要将两个或者多个结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的cpu运算,增加资源消耗及延迟。
 
10.使用子查询
子查询内部执行计划器是这样执行的:先查外表再匹配内表,而不是先查表t2,当外表的数据很大时,查询速度会非常慢。
建议使用连接(JOIN) 来代替子查询,MYSQl 不需要在内存中创建临时表来完成这个逻辑上需要两个表的查询工作。另外:如果你的应用程序有很多JOIN 查询,你应该确认JOIN 的字段是被建立过索引的。这样MYSQL 内部会启动为你优化JOIN 的sql 语句的机制。而且这些被用来JOIN的字段,应该是相同的类型的。例如:如果你要把DECIMAL 字段和一个INT 字段JOIN在一起,MYSQL 就无法使用他们的索引。对于那些STRING类型,还需要有相同的字符集才行。
 
11.使用函数索引
比如:select * from t where year(d)>= 2016
由于mysql 不像oracle 那样支持函数索引,也会直接全表扫描。
应改为---> select * from t where d>= '2016-01-01';
 
12.分组统计使用排序
分组统计可以禁止排序,避免不必要的order by 排序
比如 select name,sum(amount)  as total_score  from t group by name order by total_score
应改为---> select name,sum(amount)  as total_score  from t group by name

13.更新 clustered 索引数据列
应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。 
 
14.数值信息的字段设计为字符型
尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。 
 
15.不合理的字段类型
尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。 
 
16.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。 
 
17.使用游标
尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。
 
18.大事务操作
尽量避免大事务操作,提高系统并发能力。 
 
19.客户端返回大数据量
尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
 
 
 

MYSQl 全表扫描以及查询性能的更多相关文章

  1. Facebook对MySQL全表扫描性能的改进

    原文博客如下: http://yoshinorimatsunobu.blogspot.com/2013/10/making-full-table-scan-10x-faster-in.html 如下是 ...

  2. 造成MySQL全表扫描的原因

    全表扫描是数据库搜寻表的每一条记录的过程,直到所有符合给定条件的记录返回为止.通常在数据库中,对无索引的表进行查询一般称为全表扫描:然而有时候我们即便添加了索引,但当我们的SQL语句写的不合理的时候也 ...

  3. mysql 全表扫描、全索引扫描、索引覆盖(覆盖索引)

    full index scan:全索引扫描,查询时,遍历索引树来获取数据行.如果数据不是密集的会产生随机IO 在执行计划中是Type列,index full table scan:通过读物理表获取数据 ...

  4. mysql 全表扫描场景

    全表扫描是数据库搜寻表的每一条记录的过程,直到所有符合给定条件的记录返回为止.通常在数据库中,对无索引的表进行查询一般称为全表扫描:然而有时候我们即便添加了索引,但当我们的SQL语句写的不合理的时候也 ...

  5. MYSQL的全表扫描,主键索引(聚集索引、第一索引),非主键索引(非聚集索引、第二索引),覆盖索引四种不同查询的分析

    文章出处:http://inter12.iteye.com/blog/1430144 MYSQL的全表扫描,主键索引(聚集索引.第一索引),非主键索引(非聚集索引.第二索引),覆盖索引四种不同查询的分 ...

  6. MySql避免全表扫描【转】

    原文地址:http://blog.163.com/ksm19870304@126/blog/static/37455233201251901943705/ 对查询进行优化,应尽量避免全表扫描,首先应考 ...

  7. Mysql避免全表扫描sql查询优化 .

    对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引: .尝试下面的技巧以避免优化器错选了表扫描: ·   使用ANALYZE TABLE tbl_n ...

  8. MySql避免全表扫描

    对查询进行优化,应尽量避免全表扫描,首先应考虑在where 及order by 涉及的列上建立索引: .尝试下面的技巧以避免优化器错选了表扫描: · 使用ANALYZE TABLE tbl_name为 ...

  9. Mysql怎么样避免全表扫描,sql查询优化

    对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引: 尝试下面的技巧以避免优化器错选了表扫描: 使用ANALYZE TABLE tbl_name为扫 ...

随机推荐

  1. Debian Bug report logs - #724721 zsh: Tab completion error with vi

    Hi Ludovic, Ludovic Lebègue wrote: > While using zsh shell trying to autocomplete with tab key di ...

  2. python 函数--装饰器

    一.装饰器 1.为什么要用装饰器? 装饰器的功能:在不修改原函数以及调用方式的情况下对原函数功能进行扩展. 二.开放和封闭原则 1.对扩展是开放的 2.对修改是封闭的 三.装饰器的固有结构 impor ...

  3. Deep Dream模型与实现

    Deep Dream是谷歌公司在2015年公布的一项有趣的技术.在训练好的卷积神经网络中,只需要设定几个参数,就可以通过这项技术生成一张图像. 本文章的代码和图片都放在我的github上,想实现本文代 ...

  4. python的int float if...else

    # 字符串 string  单引号 ‘ ’  双引号 “  ”-包含的 app = 'dongt woory' 外面单引号里面可以双引号,外面双引号,里面也可以单引号 app ='你是真的“好看”吗' ...

  5. Jingwen‘s update

    Bugs: The checkin button of the question answering page must be pressed twice to check in the result ...

  6. stand up meeting 12/21/2015

    part 组员                工作              工作耗时/h 明日计划 工作耗时/h    UI 冯晓云  完成PDF UI主页面的页面切换功能,待完善    4  完善 ...

  7. 今天我们来讨论一下display和visibility两个CSS属性。

    在讨论着两个属性之前我们先来看看HTML标签的全局属性.就是可以直接在HTML标签上直接写的属性. 以下是菜鸟教程的截图: 1.看以下第一个快捷键的属性accesskey;设置的就不多说了.主要就是2 ...

  8. pytorch GPU训练好的模型使用CPU加载

    torch.load('tensors.pt') # 把所有的张量加载到CPU中 torch.load('tensors.pt', map_location=lambda storage, loc: ...

  9. [go]包和工程管理

    一.系统环境变量 GOROOT 指定go的安装目录,win是在 C\Go\,Linux在 /usr/local/go下,如果不是默认的目录,则需要指定 GOROOT环境变量,否则不需要 GOPATH ...

  10. php 对象的调用和引入

    直接上实例: 定义: <?php namespace app\php; class a { ; public function index() { echo "; } static f ...