异步编程就是使用future模式(又称promise)或者回调机制来实现(Non-blocking on waiting)。若是使用回调或事件来实现(容易callback hell),不只编写这样的代码不直观,很快就容易把代码搞得一团糟。数据库
不过在.NET 4.5 及以上框架中引入的async/await关键字(在.NET 4.0中经过添加Microsoft.Bcl.Async包也可使用),让编写异步代码变得容易和优雅。经过使用async/await关键字,能够像写同步代码那样编写异步代码,全部的回调和事件处理都交给编译器和运行时帮你处理了,简单好用。编程
使用异步编程有两个好处:不阻塞主线程(好比UI线程),提升服务端应用的吞吐量。因此微软推荐ASP.NET中默认使用异步来处理请求。promise
例如:我用异步作微信模板消息推送。缓存
/// <summary>
/// 使用异步Action测试异步模板消息接口 /// </summary>
/// <param name="checkcode"></param>
/// <returns></returns>
public async Task<string> TemplateMessageAsync(string openId, string first, string keyword1, string keyword2, string keyword3, string keyword4, string remark, string url) { if (openId == null) { return ReturnString(7771, "OPENID不能为空"); } else { var testData = new //TestTemplateData()
{ first = new TemplateDataItem(first), keyword1 = new TemplateDataItem(keyword1), keyword2 = new TemplateDataItem(keyword2), keyword3 = new TemplateDataItem(keyword3), keyword4 = new TemplateDataItem(keyword4), remark = new TemplateDataItem(remark) }; var result = await TemplateApi.SendTemplateMessageAsync(_wechat.APPID, openId, "m6td4jp_heMA5rhopbUaHApOlp2DD5x18BMXWKj3M5U", url, testData); return ReturnString(0, "成功"); } }
-》硬件服务器
集群:多台服务器分流 ,静态资源集群和动态资源集群,须要考虑session同步问题微信
CDN:使用CDN存放静态资源session
反向代理:用别的服务器代理处理并发
-》软件框架
动静分离:静态资源和动态资源分离,把静态资源放到单独的服务器异步
页面缓存:常常访问的页面能够作成静态页面放到缓存里
缩短请求路径:缩短请求服务的路径,便于解析
批量读取:多个请求合并到一块儿请求,减小数据库访问次数
延迟修改:把屡次修改请求先放到缓存中,而后同步到库
1.Where语句中不要出现Null、or、!=、<>、in、not in不然会避开索引进行全表扫描
2.尽可能避免在索引过的字符数据中,使用非打头字母搜索,不然会避开索引进行全表扫如:SELECT * FROM T1 WHERE NAME LIKE ‘%L%’
SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’
3.必要时强制查询优化器使用某个索引,如在 where 子句中使用参数,也会致使全表扫描如:select id from t where num=@num
能够改成强制查询使用索引:
select id from t with(index(索引名)) where num=@num
4.应尽可能避免在 where 子句中对字段进行表达式操做,这将致使引擎放弃使用索引而进行全表扫描。如:
SELECT * FROM T1 WHERE F1/2=100
应改成:
SELECT * FROM T1 WHERE F1=100*2
SELECT * FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)=’5378’
应改成:
SELECT * FROM RECORD WHERE CARD_NO LIKE ‘5378%’
SELECT member_number, first_name, last_name FROM members
WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21
应改成:
SELECT member_number, first_name, last_name FROM members
WHERE dateofbirth < DATEADD(yy,-21,GETDATE())
即:任何对列的操做都将致使表扫描,它包括数据库函数、计算表达式等等,查询时要尽量将操做移至等号右边。
5.应尽可能避免在where子句中对字段进行函数操做,这将致使引擎放弃使用索引而进行全表扫描。如:
select id from t where substring(name,1,3)='abc'--name以abc开头的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'
6.不要在 where 子句中的“=”左边进行函数、算术运算或其余表达式运算,不然系统将可能没法正确使用索引。
7.在使用索引字段做为条件时,若是该索引是复合索引,那么必须使用到该索引中的第一个字段做为条件时才能保证系统使用该索引,不然该索引将不会被使用,而且应尽量的让字段顺序与索引顺序相一致。
不少时候用 exists是一个好的选择:
elect num from a where num in(select num from b)
用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num)
SELECT SUM(T1.C1)FROM T1 WHERE(
(SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0)
SELECT SUM(T1.C1) FROM T1WHERE EXISTS(
SELECT * FROM T2 WHERE T2.C2=T1.C2)
二者产生相同的结果,可是后者的效率显然要高于前者。由于后者不会产生大量锁定的表扫描或是索引扫描。
若是你想校验表里是否存在某条纪录,不要用count(*)那样效率很低,并且浪费服务器资源。能够用EXISTS代替。如:
IF (SELECT COUNT(*) FROM table_name WHERE column_name = 'xxx')
能够写成:
IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx')
常常须要写一个T_SQL语句比较一个父结果集和子结果集,从而找到是否存在在父结果集中有而在子结果集中没有的记录,如:
SELECT a.hdr_key FROM hdr_tbl a---- tbl a 表示tbl用别名a代替
WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key)
SELECT a.hdr_key FROM hdr_tbl a
LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key WHERE b.hdr_key IS NULL
SELECT hdr_key FROM hdr_tbl
WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl)
三种写法均可以获得一样正确的结果,可是效率依次下降。
1.尽可能使用表变量来代替临时表。若是表变量包含大量数据,请注意索引很是有限(只有主键索引)。
2.避免频繁建立和删除临时表,以减小系统表资源的消耗。
3.在新建临时表时,若是一次性插入数据量很大,那么可使用 select into 代替 create table,避免形成大量 log ,以提升速度;若是数据量不大,为了缓和系统表的资源,应先create table,而后insert。
4.若是使用到了临时表,在存储过程的最后务必将全部的临时表显式删除,先 truncate table ,而后 drop table ,这样能够避免系统表的较长时间锁定。
5.临时表并非不可以使用,适当地使用它们可使某些例程更有效,例如,当须要重复引用大型表或经常使用表中的某个数据集时。可是,对于一次性事件,最好使用导出表。
6.在全部的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每一个语句后向客户端发送 DONE_IN_PROC 消息。
7.尽可能避免大事务操做,提升系统并发能力。
8.尽可能避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
9.避免使用不兼容的数据类型。例如float和int、char和varchar、binary和varbinary是不兼容的。数据类型的不兼容可能使优化器没法执行一些原本能够进行的优化操做。例如:
SELECT name FROM employee WHERE salary > 60000
在这条语句中,如salary字段是money型的,则优化器很难对其进行优化,由于60000是个整型数。咱们应当在编程时将整型转化成为钱币型,而不要等到运行时转化。
10.充分利用链接条件,在某种状况下,两个表之间可能不仅一个的链接条件,这时在 WHERE 子句中将链接条件完整的写上,有可能大大提升查询速度。
例:
SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO
SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO AND A.ACCOUNT_NO=B.ACCOUNT_NO
第二句将比第一句执行快得多。
1.使用视图加速查询
把表的一个子集进行排序并建立视图,有时能加速查询。它有助于避免多重排序 操做,并且在其余方面还能简化优化器的工做
2.能用DISTINCT的就不用GROUP BY
3.能用UNION ALL就不要用UNION
4.尽可能不要用SELECT INTO语句。
SELECT INOT 语句会致使表锁定,阻止其余用户访问该表。
5.尽可能避免使用游标,由于游标的效率较差