`
静妙仙人
  • 浏览: 83901 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用MySQL处理百万级以上数据时,不得不知道的几个常识

阅读更多

    最近一段时间参与的项目要操作百万级数据量的数据,普通SQL查询效率呈直线下降,而且如果where中的查询条件较多时,其查询速度简直无法容忍。之前数据量小的时候,查询语句的好坏不会对执行时间有什么明显的影响,所以忽略了许多细节性的问题。

    经测试对一个包含400多万条记录的表执行一条件查询,其查询时间竟然高达40几秒,相信这么高的查询延时,任何用户都会抓狂。因此如何提高sql语句查询效率,显得十分重要。以下是结合网上流传比较广泛的几个查询语句优化方法:

    首先,数据量大的时候,应尽量避免全表扫描,应考虑在 where order by 涉及的列上建立索引,建索引可以大大加快数据的检索速度。但是,有些情况索引是不会起效的:

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

2、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:
    
 select id from t where num is null
    
 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
    
 select id from t where num=0

3、尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:
    
 select id from t where num=10 or num=20
    
 可以这样查询:
    
 select id from t where num=10
    
 union all
    
 select id from t where num=20

4、下面的查询也将导致全表扫描:

    select id from t where name like ‘%abc%’

    若要提高效率,可以考虑全文检索。

5in not in 也要慎用,否则会导致全表扫描,如:
    
 select id from t where num in(1,2,3)
    
 对于连续的数值,能用 between 就不要用 in 了:
    
 select id from t where num between 1 and 3

6、如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:
    
 select id from t where num=@num
    
 可以改为强制查询使用索引:
    
 select id from t with(index(索引名)) where num=@num

7、应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
    
 select id from t where num/2=100
    
 应改为:
    
 select id from t where num=100*2

8、应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:
    
 select id from t where substring(name,1,3)=’abc’–nameabc开头的id
    
 select id from t where datediff(day,createdate,’2005-11-30′)=0–’2005-11-30′生成的id
    
 应改为:
    
 select id from t where name like ‘abc%’
    
 select id from t where createdate>=’2005-11-30′ and createdate<’2005-12-1′

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

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

11、不要写一些没有意义的查询,如需要生成一个空表结构:
    
 select col1,col2 into #t from t where 1=0
    
 这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:
    
 create table #t(…)

12、很多时候用 exists 代替 in 是一个好的选择:
    
 select num from a where num in(select num from b)
    
 用下面的语句替换:
    
 select num from a where exists(select 1 from b where num=a.num)

 

    建索引需要注意的地方:

1、并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段 sexmalefemale几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。

2、索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert update 的效率,因为 insert update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。

3、应尽可能的避免更新 clustered 索引数据列,因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。

 

    其他需要注意的地方:

1、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

2、任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。

3、尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。

4、避免频繁创建和删除临时表,以减少系统表资源的消耗。

5、临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。

6、在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert

7、如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。

8、尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。

9、使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。

10、与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括合计的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。

11、在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。

12、尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

13、尽量避免大事务操作,提高系统并发能力。

 

参考地址:http://www.cnblogs.com/luxf/archive/2012/02/08/2343345.html

                 http://blog.csdn.net/luyee2010/article/details/8309806

 

5
4
分享到:
评论
2 楼 aa1asdasd 2013-06-26  
楼主主要还是针对于写语句的方面
1 楼 akandfxs 2013-06-26  
百万级就这样?mysql单表几千万数据查询也没这么慢啊。
下面的一些语句优化来看你的查询可能稍微复杂一点。但这不是单表的限制了。

相关推荐

    防止服务器宕机时MySQL数据丢失的几种方案

    对于多数应用来说,MySQL都是作为最关键的数据存储中心的,所以,如何让MySQL提供HA服务,是我们不得不面对的一个问题。当master当机的时候,我们如何保证数据尽可能的不丢失,如何保证快速的获知master当机并进行...

    Mysql使用索引的正确方法及索引原理详解

    一 、介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很...索引能够轻易将查询性能提高好几个数量级。 索引相当于字典的音序表,如果要查某个字,如果不使用音序表,则需要从几

    JAVA课程设计-基于mysql的学生信息管理系统(1).doc

    实现以上各模块的功能,需要以下子功能: 1数据库连接的建立与断开 2数据库的数据操作,包括插入、查询、删除、修改 系统操作界面与数据库操作相关联 系统结构框图 从系统功能表述可以看出,该系统可以实现几个功能...

    JAVA课程设计-基于mysql的学生信息管理系统.doc

    实现以上各模块的功能,需要以下子功能: 1数据库连接的建立与断开 2数据库的数据操作,包括插入、查询、删除、修改 系统操作界面与数据库操作相关联 系统结构框图 从系统功能表述可以看出,该系统可以实现几个功能...

    mysql数据库索引自学笔记,基础+单表索引+多表索引的创建方法及原理

    因为索引行是按索引键的顺序存储的,所以当索引键中有一列被更新时,DBMS可能不得不把相应的行从旧的索引位置移到新的位置来保持这一顺序,所以不稳定的列不建议被索引。在实际开发中,这个问题不可能避免(比如按...

    MySQL性能调优之MemoryorSSD?

    当一个传统的向外扩展的方式对于MySQL来讲变得流行,看看我们不得不扩充哪一方面(便宜的内存?快速存储?更好的电源效率?)将会变得非常有趣。这里确实有很多种选择——我每周大概会遇到一个客户使用Fushion-IO 卡...

    MySQL索引原理以及查询优化

    一般的应用系统,读写比例在10:1左右,...索引能够轻易将查询性能提高好几个数量级。索引相当于字典的音序表,如果要查某个字,如果不使用音序表,则需要从几百页中逐页去查。索引的目的在于提高查询效率,与我们查阅图

    数据结构通讯录系统需求分析报告.doc

    系统软件需求 IIS5.0以上的WEB服务、安装有 Myeclipse8.5与Mysql5.1数据库等、Windows XP 以及更高版本的操作系统、IE5.0以上的版本浏览器。 3.3 用户的特点 管理员,具备基本的电脑操作技能和简单的系统维护工作;...

    支持php4、php5的mysql数据库操作类

    前端一直使用PHP5,的确使用起来特别的爽,现在为了能在俺的虚拟主机上跑,不得不改成PHP4的。这几个库类我以前发在PHPCHIAN,地址是http://www.phpchina.com/bbs/viewthread.php?tid=5687&highlight=。(前几天在...

    JSF1.2+EJB3.0实现的一个项目实例

    此时还需要在web端的类路径中(也就是在jsfejb3-war项目的lib文件夹中)添加以下几个Jar包(这些包都在JBoss服务器安装目录/client目录下有):ejb3-persistence.jar、hibernate-client.jar、javassist.jar、jboss-ejbs-...

    ebsite for net4.0网站建设系统 v3.0 正式版.zip

    如今互联网产品如如雨后春笋般层出不穷,程序员们每天都要面对变化无穷的需求,来满足产品的需要,他们不得不加班加点,来完成他们的使命,由最初的web1.0,web2.0,3.0到现在的移到互联网,可谓是变化莫测。...

    水云斋网站管理系统2.0

    软件更新:修正了几个模版错误;修正了无法生成软件分类列表的错;修正了无法添加软件缩略图的错误。2004-8-20本次更新的方法:修正了无法生成软件分类列表的错误及无法添加缩略图的错误,更正了部分模版问题~!请...

    mahara教师评价系统

    } 注意对于 openssl_pkey_export 函数,因为加 config 的缘故第三个参数即密码也不得不 加上(不能省略中间一个默认参数),这样就给别的地方的解密带来麻烦,故还要改一个地 方。同一个文件中 OpenSslRepo 类的...

    PHP基础教程 是一个比较有价值的PHP新手教程!

    CGI程序的伸缩性不很理想,因为它为每一个正在运行的CGI程序开一个独立进程。解决方法就是将经常用来编写CGI程序的语言的解释器编译进你的web服务器(比如mod_perl,JSP)。PHP就可以以这种方式安装,虽然很少有人愿意...

    最新Java面试题视频网盘,Java面试题84集、java面试专属及面试必问课程

    │ Java面试题04.java中int占几个字节.mp4 │ Java面试题05.java面向对象的特征.mp4 │ Java面试题06.装箱和拆箱.mp4 │ Java面试题07.==和equals的区别.mp4 │ Java面试题08.String.mp4 │ Java面试题09.讲一下java...

    cms!NT2.0版本源码

    遵从 GENERAL PUBLIC LICENSE(GPL) 开源协议,这意味着可以修改程序的一个或几个副本或程式的任何部分,以此形成基於这些程式的衍生作品。必须在修改过的档案中附有明显的说明:您修改了此一档案及任何修改的日期。...

    X3BLOG AJAX国产大型开源多用户博客系统 1.1.0.beta1源码版

    X3-BLOG 遵从 GENERAL PUBLIC LICENSE(GPL) 开源协议,这意味着可以修改程序的一个或几个副本或程式的任何 部分,以此形成基於这些程式的衍生作品。必须在修改过的档案中附有明显的说明:您修改了此一档案及任何...

Global site tag (gtag.js) - Google Analytics