一:理解sql执行顺序javascript
在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.html
sqlserver 2005 各个环节简单介绍:java
(8)SELECT (9)DISTINCT (11)<Top Num> <select list>mysql
(1)FROM [left_table]sql
(3)<join_type> JOIN <right_table>数据库
(2)ON <join_condition>服务器
(4)WHERE <where_condition>并发
(5)GROUP BY <group_by_list>app
(6)WITH <CUBE | RollUP>ide
(7)HAVING <having_condition>
(10)ORDER BY <order_by_list>
a)各个步骤简介:
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
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 语句,若是只更改一、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引擎.