一:理解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 各个环节简单介绍:

  1. (8)SELECT (9)DISTINCT (11)<Top Num> <select list>
  2. (1)FROM [left_table]
  3. (3)<join_type> JOIN <right_table>
  4. (2)ON <join_condition>
  5. (4)WHERE <where_condition>
  6. (5)GROUP BY <group_by_list>
  7. (6)WITH <CUBE | RollUP>
  8. (7)HAVING <having_condition>
  9. (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涉及的列,不要留空,创建表时赋予初始值

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

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

   

  1. 错误
  2. select id from table where id <> 100

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

  

  1. select id from table where num=1 or Name = 'zhangsan'
  2. 建议修改为
  3. select id from table where num=1
  4. unionall
  5. select id from table where name = 'zhangsan'

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

  

  1. 最早此处sql有误,感谢 宝宝心里苦,宝宝不说  的指出。
    select id from t where role in (select rid from role where rName = '经理')
  2. 建议修改为
  3. 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 中尽量不要出现表达式计算

  如:

  1. select id from t where num/2 = 100

  应改为:

  1. 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:不要写一些没有意义的查询,如需要生成一个空表结构:

  1. 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. tmux frequently asked questions

    tmux frequently asked questions How is tmux different from GNU screen?     tmux and GNU screen have ...

  2. 使用flex

    Flex如何处理二义性模式: 1.词法分析器匹配输入时匹配尽可能多的字符串 2.如果两个模式都可以匹配的话,匹配在程序中更早出现的模式 上下文相关的记号 flex提供起始状态(start state) ...

  3. EDI数据导入的注意事项&常见异常处理

    EXCEL表格注意事项: •      编码是0开头的,格式必须是文本,否则前面请加字母: •      注意全角半角,中文标点英文标点: •      编号文字类开头和结尾不要有空格,姓名中间也不要 ...

  4. 快速排序Golang版本

    Created by jinhan on --. Tip: http://blog.csdn.net/zhengqijun_/article/details/53038831 See: https:/ ...

  5. [react] React 新手必须知道的 N 件事

    尽量用 props & onChange,不要用 ref 获取引用然后调用方法.详情参考我的文章:一等公民 props & onChange React 只是一个视图框架,请尽量在 C ...

  6. Tinc VPN

    服务端配置 安装 $ apt-get install tinc 配置 $ mkdir -p /etc/tinc/dock/hosts $ cd /etc/tinc/dock 配置 tinc.conf ...

  7. python随机图片验证码的生成

    Python生成随机验证码,需要使用PIL模块. 安装: 1 pip3 install pillow 基本使用 1. 创建图片 1 2 3 4 5 6 7 8 9 from PIL import Im ...

  8. I/O复用中的 select poll 和 epoll

    I/O复用中的 select poll 和 epoll: 这里有一些不错的资料: I/O多路复用技术之select模型: http://blog.csdn.net/nk_test/article/de ...

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

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

  10. 【LintCode·入门】斐波那契数列

    斐波那契数列 描述 查找斐波纳契数列中第 N 个数. 所谓的斐波纳契数列是指: 前2个数是 0 和 1 . 第 i 个数是第 i-1 个数和第i-2 个数的和. 斐波纳契数列的前10个数字是: 0, ...