一:理解sql执行顺序

在sql中,第一个被执行的是from语句,每一个步骤都会产生一个虚拟表,该表供下一个步骤查询时调用,比如语句:select top 10 column1,colum2,max(column3) from user where id>1 group by column1,colum2 having count(column1)>1 order by colum2.

sqlserver 2005 各个环节简单介绍:

(8)SELECT (9)DISTINCT  (11)<Top Num> <select list>
(1)FROM [left_table]
(3)<join_type> JOIN <right_table>
(2)ON <join_condition>
(4)WHERE <where_condition>
(5)GROUP BY <group_by_list>
(6)WITH <CUBE | RollUP>
(7)HAVING <having_condition>
(10)ORDER BY <order_by_list>

  a)各个步骤简介:

  1. FROM:对FROM子句中的多个表执行笛卡尔积(Cartesian product)(交叉联接),生成虚拟表VT1
  2. ON:对VT1应用ON筛选器。只有那些使<join_condition>为真的行才被插入VT2。
  3. OUTER(JOIN):如 果指定了OUTER JOIN(相对于CROSS JOIN 或(INNER JOIN),保留表(preserved table:左外部联接把左表标记为保留表,右外部联接把右表标记为保留表,完全外部联接把两个表都标记为保留表)中未找到匹配的行将作为外部行添加到 VT2,生成VT3.如果FROM子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,直到处理完所有的表为止。
  4. WHERE:对VT3应用WHERE筛选器。只有使<where_condition>为true的行才被插入VT4.
  5. GROUP BY:按GROUP BY子句中的列列表对VT4中的行分组,生成VT5.
  6. CUBE|ROLLUP:把超组(Suppergroups)插入VT5,生成VT6.
  7. HAVING:对VT6应用HAVING筛选器。只有使<having_condition>为true的组才会被插入VT7.
  8. SELECT:处理SELECT列表,产生VT8.
  9. DISTINCT:将重复的行从VT8中移除,产生VT9.
  10. ORDER BY:将VT9中的行按ORDER BY 子句中的列列表排序,生成游标(VC10).
  11. TOP:从VC10的开始处选择指定数量或比例的行,生成表VT11,并返回调用者.

  b)标准sql执行顺序是:

  1:form 组装来自不同表的数据,如 form user或者,form user as u join goodsOrder as r on u.id= r.userid

  2:where 过滤符合查询条件的数据,如:id>1000

  3:group by 将查询数据进行分组

  4:使用sum等聚合函数进行计算。

  5:使用having 进行筛选分组。

  6:执行select语种

  7:执行排序语句

  如:select count(gid),gname from shopping_goods where gcid=1 group by gname having count(gid)>1 order by count(gid) desc

  1:首页查询shopping_goods 表,得到表中的数据

  2:执行where,过滤出gcid=1的商品。

  3:对gname进行分组。

  4:使用聚合函数count(),计算出商品类型为1,不同商品名称的数量.

  5:使用having,过滤出类型为1,商品统计数量大于1的商品

  6:执行select语句

  7:执行order by ,按照商品数量降序排列。

二:百万数据量优化

  这里只介绍查询和修改的方法,如果是系统优化,需要从表结构,索引,表分区等方面处理。

  1:合理使用索引,在一个大数据量的表中,并不是索引越多越好,索引越多,写操作越慢,建议在以下字段上创建索引。

  ●在经常进行连接,但是没有指定为外键的列上建立索引,而不经常连接的字段则由优化器自动生成索引。

  ●在频繁进行排序或分组(即进行group by或order by操作)的列上建立索引。

  ●在条件表达式中经常用到的不同值较多的列上建立检索,在不同值少的列上不要建立索引。比如在雇员表的“性别”列上只有“男”与“女”两个不同值,因此就无必要建立索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度。

  ●如果待排序的列有多个,可以在这些列上建立复合索引(compound index)。

  ●使用系统工具。如Informix数据库有一个tbcheck工具,可以在可疑的索引上进行检查。在一些数据库服务器上,索引可能失效或者因为频繁操作而使得读取效率降低,如果一个使用索引的查询不明不白地慢下来,可以试着用tbcheck工具检查索引的完整性,必要时进行修复。另外,当数据库表更新大量数据后,删除并重建索引可以提高查询速度。

  2:尽量少用(或者不用)sqlserver 自带的函数

  a):如dateadd(month,-1,getdate()),请使用time>'2017-09-19 23:42:44.770 '代替dateadd.

  b):如datediff(day,'2017-10-20','2017-10-25'),select datepart(day,getdate());,如需计算两个日期之前的差值,或者得到日期中的整数部分,建议查询完毕后用java程序来计算,不要什么都让数据库来做.

  c:) 如:substring(name,1,3) = ’abc’,建议修改为 name like 'abc%'

  3:尽量不要在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,强烈建议where涉及的列,不要留空,创建表时赋予初始值

错误
select id from table where name is not null
正确
create table table(name varchar(20) default '')

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

   

错误
select id from table where id <> 100

  5:应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描,建议使用unall 来代替or

  

select id from table where num=1 or Name = 'zhangsan'
建议修改为
select id from table where num=1
unionall
select id from table where name = 'zhangsan'

  6:建议使用exists 来代替in,能用between 就不要使用in 如:age in (20,21,22)建议修改为:age between 20 and 22

  

最早此处sql有误,感谢  宝宝心里苦,宝宝不说  的指出。
select id from t where role in (select rid from role where rName = '经理')
建议修改为
select id from t as a where exists (select rid from role as b where a.role = b.rid and rName = '经理')

  7:like 的用法

  除了 title  like '重庆%' ,其它使用方法(如:title like  '%王%' title like '%天')也将导致全表扫描

    8:where 中尽量不要出现表达式计算

  如:

select id from t where num/2 = 100

  应改为:

select id from t where num = 100*2

  9:Update 语句,如果只更改1、2个字段,不要Update全部字段,否则频繁调用会引起明显的性能消耗,同时带来大量日志。强烈建议修改时使用动态sql语句,类似hibernate中dynamic-update=true,不过hibernate需要将修改对像通过id查询出来,才会动态修改,如果是普通sql,直接组装就可以。

  10:对于多张大数据量(这里几百条就算大了)的表JOIN,要先分页再JOIN,否则逻辑读会很高,性能很差.

  11:不要写一些没有意义的查询,如需要生成一个空表结构:

select col1,col2 into #t from t where 1=0

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

  13:尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

  14:不建议使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。

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

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

  17:尽量避免大事务操作,提高系统并发能力。并且不要事务嵌套,不要在事务中去调用其它系统的接口,不要在事务中耗时操作,不然死锁并伴你左右。

  18:尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。(笔者曾经处理过,从3000万手机号码库中,模糊查询出上万个手机号码,这种需求是客户硬性要求,就要通过executorservice了,不要直接写sql查)

  19:如果数据库是mysql,一定要利用数据库引擎,不同业务要使用不同的数据库引擎。比如常用的innodb和myisam,innodb支持事务,支持外键,锁是表级锁,缺点是查询速度慢,Myisam 的执行速度更快,性能更好,但不支持外键,不支持事务,锁是行锁级。比如日志表,数据量大,强烈建议使用myisam引擎.

  以上有些来自网络,有些来自工作中的总结,后期还会完善,如有错误,请指出,谢谢。

sql语句百万数据量优化方案的更多相关文章

  1. <搬运> SQL语句百万数据量优化方案

    一:理解sql执行顺序 在sql中,第一个被执行的是from语句,每一个步骤都会产生一个虚拟表,该表供下一个步骤查询时调用,比如语句:select top 10 column1,colum2,max( ...

  2. sql server 百万级数据库优化方案

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  3. 数据库SQL优化大总结之 百万级数据库优化方案(转载)

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...

  4. mysql 百万级数据库优化方案

    https://blog.csdn.net/Kaitiren/article/details/80307828 一.百万级数据库优化方案 1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 wher ...

  5. PHP如何通过SQL语句将数据写入MySQL数据库呢?

    1,php和MySQL建立连接关系 2,打开 3,接受页面数据,PHP录入到指定的表中 1.2两步可直接使用一个数据库链接文件即可:conn.php <?phpmysql_connect(&qu ...

  6. 通过Sql语句导数据

    在通过SQL Server向导中的SQL语句导数据时,默认情况下源表中的nvarchar字段类型会变成202,解决此问题的方法是,要重新选择一下对应的数据接收表.

  7. SQL语句之 数据约束

    SQL语句之 数据约束 什么是数据约束 数据约束用来限制用户对数据的非法的修改操作. 1.约束字段的默认值 如果插入记录时,没有给某个字段赋值,那么我们可以设置它的默认值 关键字:default CR ...

  8. 使用SQL语句进行数据复制

    使用SQL语句对数据或者表进行复制,一般用于两张表结构相同的时候使用. SQL Server中,如果目标表存在: insert into 目标表 select * from 原表; SQL Serve ...

  9. 数据库SQL优化百万级数据库优化方案

    1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

随机推荐

  1. DevExpress.XtraEditors.TextEdit 设为密码输入框

    DevExpress.XtraEditors.TextEdit 设为密码输入框,解决办法: 设计窗口-->属性Properties-->Mask节点-->PasswordChar输入 ...

  2. 数据库中File权限的危害

    The FILE privilege gives you permission to read and write files on the server host using the LOAD DA ...

  3. 使用MongoVUE

    mongoDB版本号为3.4.10 在终端操作一顿后想看看它在可视化工具里面什么样子,于是就找了一个可视化工具,MongoVUE这个看起来还不错,因为我是windows系统所以就没有太多的挑选选择.在 ...

  4. Akka(37): Http:客户端操作模式

    Akka-http的客户端连接模式除Connection-Level和Host-Level之外还有一种非常便利的模式:Request-Level-Api.这种模式免除了连接Connection的概念, ...

  5. 10. 管理Apache ZooKeeper配置

    Tips 有关ZooKeeper部署和管理的详细说明,请参阅官方文档http://zookeeper.apache.org/doc/trunk/zookeeperAdmin.html. 1. 配置Zo ...

  6. 搭建php环境的几种方法

    对于想学习php开发初学者来说,先要学习搭建php开发环境,因为要做php开发,搭建一个能够运行php网站的服务器环境是第一步,传统的php环境软件非常复杂,好在很多公司开发了一键搭建php安装环境, ...

  7. 一步步搭建最简单oauth2.0认证和授权

    oauth2.0 最早接触这个概念是在做微信订阅号开发.当时还被深深的绕进去,关于oauth2.0的解释网上有好多,而且都讲解的比较详细,下面给大家价格参考资料. http://owin.org/ h ...

  8. 《Linux命令行与shell脚本编程大全》第二十章 正则表达式

    20.1 什么是正则表达式 20.1.1 定义 正则表达式是你所定义的模式模板.linux工具可以用它来过滤文本. 正则表达式利用通配符来描述数据流中第一个或多个字符. 正则表达式模式含有文本或特殊字 ...

  9. 当使用javac编译源文件时,如何查找import导入的类

    当编写一个java源代码文件时,此文件通常被称为编译单元(有时也被称为转移单元).每个编译单元都必须有一个后缀名.java,而在编译单元内则可以有一个public类,该类的名称必须与文件名称一致.每个 ...

  10. C#在自定义事件里传递自定义数据,使用EventArgs的姿势

    EventArgs是包含事件数据的类的基类,用于传递事件的细节.今天分享的是使用泛型来约束EventArgs,在事件里传递自定义数据的例子. 正题 由于这个关注点很小,直接上代码了. 定义泛型类TEv ...