索引的力量

一直对数据库的优化一窍不通,大家谈论最多应该是怎样从 SQL 查询语句和索引下手去优化。对于索引,很多高手都写过很多文章,看来看去也没悟出什么东西,不过,今天我修改了数据表的几个主键(可以认为就是聚焦索引)并且添加了一些非聚焦索引,SQLServer 的性能立刻提高了上去。

对于 Users 表,原先是把主键设置为 UserID(自增字段)字段上,通过事件跟踪器,发现对于 Users 表的查询比较耗费资源(可以从 CPU、Reads、Duration这三相值来判断),而且所有的查询基本上都是对 Users 表的 name 来查询的,即 SELECT * FROM users WHERE name = 'xxx',既然WHERE后边跟的是 name,就应该把聚焦索引设置到 name 字段上,并且 name 字段是不重复的,所以可以这样修改。修改前的耗费忘了记录了,修改之后的耗费大大降低了,CPU、Reads、Duration分别为0、9、0。如果WHERE后面跟的字段是可重复的,就不能作为聚焦索引,这时可以为该字段添加非聚焦索引。

按照这个思路来优化其他表。

select count(*) from mark where name = 'xxx'
优化前
CPU / Reads / Duration(下同)
15 / 1401 / 16
32 / 1422 / 30
31/  1422/  46
优化后: 对mark表加入name以及infoid的非聚焦索引
0 /  38 /  0
15 /  39 /  16
0 /  12 /  0
0 /  81 /  0
0 /  37 /  30
0 /  12 /  0

select * from comment where infoid = '12345'
优化前:
0 / 644 / 0
15 / 664 / 16
优化后:comment表给infoid加非聚焦索引
0 / 158 / 0
0 / 158 / 0
16 / 42 / 16
0 / 42 / 0

对所有表都经过类似的优化后,性能立刻提升了上去,CPU 从原先的 95% 左右降低到 60% 左右。由此可见,对于表的设计应该非常重视主键的选择,不要为每个表都来一个 int 类型的自增字段作为主键,另外就是跟踪数据库查询,根据具体的查询来建立非聚焦索引。

不清楚 ASP.NET 到底能承受多大的页面浏览量,虽然这个问题问的太宽泛,但总体印象上,对 ASP.NET 的性能有所怀疑。大型 Web 好像也没有几个用 ASP.NET 做的,dangdang 网是的,圣诞节的时候去访问,老是出现页面打不开的故障;DoNews 也是,不过,也是经常出现那非常熟悉的错误页面,至于 MySpace,没有太多关注。

看到关于豆瓣的一组数据,很是羡慕:一台Web服务器运行 Lighttpd,每天处理2500万个request,峰值每秒处理1000个request; 一台应用服务器运行Python,每天处理500万PV; 数据库服务器运行MySQL,负载情况没有介绍。

对于特别注重速度的web2.0年代里,觉得 Python、PHP、ROR 这些轻量级的框架来做 Web 开发将更加适合,再加上免费的 Linux 平台以及 MySQL数据库,最理想不过了。微软也搞了一个 MVC 框架,呵呵,是不是觉察到了一些危机了呢?

posted @ 2008-01-21 21:28 卡卡 ^ cacard 阅读(2409) 评论(50)  编辑 收藏 所属分类: ASP.NET

  回复  引用  查看    
#1楼 2008-01-21 21:32 | 武眉博<活靶子.Net>      
一般常where ,order by 的字段 索引效果比较好
  回复  引用  查看    
#2楼 2008-01-21 22:25 | Jeffrey Zhao      
为什么“如果WHERE后面跟的字段是可重复的,就不能作为聚焦索引”呢?还有不用对ASP.NET的性能有怀疑,主流服务器端技术的性能都差不多,因为瓶颈不在这里。微软的MVC框架也不是因为性能的考虑,而是开发方式上。
  回复  引用  查看    
#3楼 [楼主]2008-01-21 22:57 | 卡卡 ^ cacard      
@Jeffrey Zhao

如果WHERE后面跟的字段是可重复的,就不能“单独”作为聚焦索引,是吗?
对于性能来说,我觉得是这样,大部分程序员用ASP.NET的开发出的东西,会存在潜在的性能问题,当然,对于高手来说,用什么都无所谓了。

谢谢老赵的回复,呵呵,欢迎指正我的错误,同时,希望与您取得联系,我的MSN:Billgate(at)live.com 或者向我发一封Email:Cacard(at)126.com,Thanks。
  回复  引用  查看    
#4楼 2008-01-21 23:23 | aspnetx      
@Jeffrey Zhao
虽然不太完全认同老赵的看法,不过还是来支持一下.
  回复  引用    
#5楼 2008-01-21 23:58 | xmlcss [未注册用户]
@卡卡 ^ cacard
那是不是可以这样说
对于性能来说,我觉得是这样,大部分程序员用PHP的开发出的东西,会存在潜在的性能问题,当然,对于高手来说,用什么都无所谓了。

或者把 PHP 换成其他 技术/语言.
  回复  引用  查看    
#6楼 2008-01-22 00:02 | Jeffrey Zhao      
@卡卡 ^ cacard
不知道你觉得是什么导致ASP.NET性能低下的呢?
// 聚集索引并不排斥相同的值啊,只是由于聚集索引的特点,最好存放重复较少的字段——还有其实如果后生成的值总是大于之前生成的值,其实也适合用聚集索引的。
  回复  引用  查看    
#7楼 2008-01-22 00:03 | Jeffrey Zhao      
@aspnetx
呵呵,哪个地方不同意啊?:)
  回复  引用  查看    
#8楼 2008-01-22 00:18 | TT.Net      
主键不是默认就有非聚集索引吗?
  回复  引用  查看    
#9楼 2008-01-22 00:56 | Muse      
聚焦索引?聚集索引吧!
---

大部分表加int类型的id是为了高效的表间关联检索,而不是为了本身的检索效率。

聚集索引不适合于那些变化频繁(并且数据没有规律)的表,这会严重的影响性能,数据越多,影响越大,最终可能得不偿失。

所谓的聚集索引,就是将值按照排好的顺序存储,这也是为什么顺序增长的列特别适合于聚集索引的原因。

数据查询有很多方法进行优化,而数据结构的设计对其影响最大,一个不合理的数据结构,怎么索引都不会太快的。
  回复  引用  查看    
#10楼 2008-01-22 01:06 | xingd      
大众点评网(dianping.com)使用的就是ASP.NET。

索引是数据库性能优化非常重要的一个方面,很多时候处理起来要比较谨慎。简单的把name设为聚集索引不一定非常理想的,在其它关联表里如果还是存储的userid,那就得不偿失了。

当网站,尤其是Web 2.0网站到达一定规模后,性能是受架构和技术团队的整体实力影响的,与平台没有必然的联系。
  回复  引用  查看    
#11楼 2008-01-22 01:11 | Muse      
再加一句话,关于ASP.NET的性能的。
ASP.NET的性能提高是很明显的,但这是对与往日的asp来说,而对于其他语言来说,就不清楚了。

说来说去还是那句话:设计决定性能。
我们曾经做过很多代码和逻辑的优化,按照一般思路和改进后的思路,一般都会相差几或几十倍,而最夸张的一次,达到1000多倍。
1000多倍的这种情况毕竟少见,但几十倍的性能优化,就不是语言之间的差距能解决了,所以代码优化是在每时每刻进行的,你的一闪念可能就会让CPU节省大量的运行时间,最重要的是,你的程序是不断的运行的,你的优化所产生的效益可不是节省几秒或几十、几百毫秒的问题。
  回复  引用  查看    
#12楼 2008-01-22 08:21 | 苯苯的考拉熊      
老兄还是应该好好理解一下聚簇索引和非聚簇索引的工作模式,就不会有这种讨论了。
  回复  引用    
#13楼 2008-01-22 09:12 | Everett [未注册用户]
聚焦索引? 我以前看过的说法怎么都叫聚簇索引呢
  回复  引用  查看    
#14楼 2008-01-22 09:19 | henry      
如果楼主一直用webform做开发,那应该说webfrom下进行应用开发给楼主感到有性能问题而不是asp.net.
好的服务器峰值每秒处理1000个request不难,问题在于这个请下的所有资源处理是不是都由这台服务独自完成?服务器的配置又是怎样?
还有asp.net mvc 请看一下是以什么开头的,其作用是给开发人提供另一种模式进行web应用开发,但平台还是基于asp.net.
  回复  引用  查看    
#15楼 2008-01-22 10:39 | Clark Zheng      
唉,老赵的回复都这么专业,同样是地球人为什么差距这么大捏?
  回复  引用  查看    
#16楼 2008-01-22 10:41 | Yoshow      
聚焦索引 等于 聚簇索引 么

这种索引我一般还是习惯建在Int型上, 不是很喜欢建在varchar型上.
  回复  引用  查看    
#17楼 [楼主]2008-01-22 11:04 | 卡卡 ^ cacard      
@Jeffrey Zhao
我个人觉得ASP.NET性能低下的原因是Webfrom封装了太多的东西,特别是那个runat=server的from,提交的时候,其实向Server回送了太多没有必要的值。其它方面,.NET这个框架是在Windows上面更高一个层次的集成,性能总会所有降低。
  回复  引用  查看    
#18楼 [楼主]2008-01-22 11:05 | 卡卡 ^ cacard      
@xingd
能否简单说明一下什么是“架构”?
  回复  引用  查看    
#19楼 [楼主]2008-01-22 11:07 | 卡卡 ^ cacard      
@Muse
Muse说“说来说去还是那句话:设计决定性能。
我们曾经做过很多代码和逻辑的优化,按照一般思路和改进后的思路,一般都会相差几或几十倍,而最夸张的一次,达到1000多倍。 ”

//“设计”这个词其实很宽泛,真希望你能把你的优化经验写出来,期待。
  回复  引用  查看    
#20楼 [楼主]2008-01-22 11:08 | 卡卡 ^ cacard      
@苯苯的考拉熊
嗯,有待了解。
  回复  引用  查看    
#21楼 [楼主]2008-01-22 11:09 | 卡卡 ^ cacard      
@Everett
两种叫法。
  回复  引用  查看    
#22楼 2008-01-22 11:11 | Cameo      
受教了
  回复  引用  查看    
#23楼 [楼主]2008-01-22 11:11 | 卡卡 ^ cacard      
@henry
??
Webfrom不是ASP.NET的一部分吗?
是不是可以这样说,开发ASP.NET程序时,我一点都不用WebFrom的东西,性能就会没有问题呢?觉得ASP.NET MVC其实就是抛弃了WebFrom。

  回复  引用  查看    
#24楼 [楼主]2008-01-22 11:14 | 卡卡 ^ cacard      
@Muse
“数据结构的设计”!
到底什么是“数据结构的设计”呢?
  回复  引用  查看    
#25楼 2008-01-22 11:17 | cslar      
看一看petshop 4.0的设计,在这样的架构下的应用程序运行时多么的流畅,起码比起petstore来说性能提高了不少。。。
  回复  引用  查看    
#26楼 2008-01-22 11:18 | henry      
@卡卡 ^ cacard
webform是asp.net一个默认实现的开发结构.
请你搞清楚一个问题,用WebFrom不代表性能有问题,用MVC不代表性能没问题.
分布式设计从一个程序处理角度明显是降低了处理效率,但为什么这样干?
做系统要考虑的东西有很多,不要太盲某一方面的问题.
如果你是硬是要说谁性能好,那我只能告诉你80%的问题来自于程序员编写的代码,而不是框架本身.
  回复  引用  查看    
#27楼 [楼主]2008-01-22 11:26 | 卡卡 ^ cacard      
@henry
嗯,“80%的问题来自于程序员编写的代码”,ASP.NET没问题,我觉得,ASP.NET更倾向于让程序员编写的代码“有问题”,从而影响了性能,这算不算ASP.NET这个框架的一个小问题呢?
  回复  引用  查看    
#28楼 2008-01-22 11:33 | henry      
@卡卡 ^ cacard
ASP.NET更倾向于让程序员编写的代码“有问题”
那只说明了那些程序只为了完成功能写代码,而不去考虑这样做是否合适.
导致这问题的主原因是程序员对asp.net不够了解.我们是不是应该面墙思过,而不是把问题算到ASP.NET头上?
  回复  引用  查看    
#29楼 [楼主]2008-01-22 11:38 | 卡卡 ^ cacard      
@henry
嗯,大家“面墙思过”吧,当你使用一些很“方便”的Webfrom控件时,是否考虑到其对性能的影响呢?开发效率和程序性能两手都要抓啊。
  回复  引用  查看    
#30楼 2008-01-22 11:47 | henry      
项目要考虑的东西实在是太多了,在计较那20%的性能之前,我们是否已经把那由代码所产生的80%性能所解决掉?如果我们对代码所产生的80%性能都解决不了,那换到那个平台下结果都一样.
问题的本质就如同本文标题一样,索引没建好查询速度慢就怪到数据库头上,那最终是用什么数据库都面对结果都是一样.
  回复  引用  查看    
#31楼 2008-01-22 11:54 | xingd      
什么是设计,什么是架构,我不想回答这两个问题,回答了也没用.

单机性能是一方面, 可读性/扩展性/重用性/团队开发支持是其它的方面。回复这篇blog,只是举dianping.com的例子,说明ASP.NET本身并不慢。无意跟你争论任何的具体问题。
  回复  引用  查看    
#32楼 2008-01-22 12:11 | xingd      
就索引来说,需要考虑哪些方面

1. cluster还是non-cluster
2. 索引的使用情况和维护成本,index lookup, index seek, index scan, index udpate的比例如何。
3. 是否将索引存储到单独的file group
4. 索引的fill factor应该设置为多大
5. 是否启用Sort in TempDB
6. 是否打开Auto Statistic,是否可以定时update
7. 索引碎片产生的频度如何,多久做一次reorganize,多久一次rebuild
8. 配置SQL Server为每索引分配的最低内存为多少
9. 是否需要增加额外的Included column
10. 如何利用多个索引的共同使用提高查询效率
11. 是否需要在query hint里指定此索引,或者指定join为merge join, loop join或者hash join
12. 超大数据表时,如何做表分区和索引分区。


  回复  引用  查看    
#33楼 2008-01-22 13:10 | Randy0528      
我在一边看看就好。呵呵。
  回复  引用  查看    
#34楼 2008-01-22 13:36 | Muse      
@卡卡 ^ cacard
"数据结构"
在数据库上就是表的结构、关联关系等等
在程序上就是个种类、模块的设计及其与其它类、模块之间的关系等

数据结构都够写本大书了,哪是几句话能说得清的?何况,我还不是数据结构专家。

关于优化,只是日常调试程序的常规工作,实在谈不出什么经验。不过倒是有一条,我们眼中性能好的程序表现就是:当用户按下按钮的时候,你的程序要立即提供反馈,如果是查询,除非数据量超大,要立即显示出来(立即一般在0.5秒内),即使数据量超大,也要能先显示一部分。总的来说,就是用户无需等待。
  回复  引用  查看    
#35楼 2008-01-22 13:47 | Jeffrey Zhao      
WebForm性能“理论上”会降低性能,因为需要构造控件等等,但是这些东西的性能“损失”完全可以忽略不计,对于一个应用来说,有太多东西影响性能。比如连接一个数据库,底得上无数个控件构造了。
还有就是ASP.NET MVC,它的View层就是完整WebForms模型,生命周期啥啥一切都在,如果说性能提高,理由在什么地方呢?
  回复  引用  查看    
#36楼 [楼主]2008-01-22 13:52 | 卡卡 ^ cacard      
@Jeffrey Zhao
不说了,免得引起什么误解,对MVC还没有研究,所以还没有发言权。
  回复  引用  查看    
#37楼 2008-01-22 14:08 | 坏人      
峰值每秒处理1000个request; 一台应用服务器运行Python,每天处理500万PV

这个数据并不代表什么.

每秒1000个请求的计算是包含了图片等所有资源的,一个正常的HTML页面基本会包括十个以上这样的请求,每天500万的PV这个量,一台服务器顶下来并非难事,而且这些都针对的是WEB前端的性能,很容易可以得到.

更实际一点的计算方法为,前端WEB的每秒峰值PV以及每个PV造成的数据库压力以及周边服务器的压力计算总合,比如图片服务器,比如缓存服务器等等,一个稍大型的WEB应用,通常都会有多台静态资源服务器用于存储脚本、图片、CSS等内容,以分摊IO的压力,要知道,WEB服务器通常IO的瓶颈会先于CPU等暴露出来,至于应用服务器通常会涉及到更多计算量,这个不好评估,一般也是按每个PV造成的负荷压力作为附加值来计算的,缓存服务器与数据服务器也是如此。

所以,综合来看,评定的方法,比较理想的方式是以WEB前端为中心,资源、应用、数据、缓存等服务器围绕成为每个PV的附加压力,作为最终的负载计算结果。

所以你并不用羡慕豆瓣的以上数据,而且具我所知,豆瓣更多的是在做数据挖掘,所以他的性能高低应当集中体现在数据挖掘那台或那几台服务器上,如果他的数据挖掘做得不够深入,那么他的性能压力应当会出现于数据库服务器上,WEB前端他的压力应当不会比一般的非分析性网站要大。
  回复  引用    
#38楼 2008-01-22 14:24 | zbh [未注册用户]
聚集索引和非聚集索引,自己去看SqlServer联机帮助.
两三句话是不能说清楚的
  回复  引用    
#39楼 2008-01-22 14:31 | rqrq [未注册用户]
聚集索引应该设在userid上,username应该设置唯一索引或者非聚集索引
  回复  引用  查看    
#40楼 2008-01-22 15:26 | PerfectDesign      
主键不可以重复,而聚集索引可以重复。
但是最佳实践是聚集索引最好也不要重复,重复的话数据库内部会做一个唯一重复聚集索引的维护。比如聚集索引上有name : xx 和 xx ,那么mssql会自动在内部将其命名为xx(1) xx(2)
这个效果比较差的。而且这个内部索引值是个int值,32位,也会占用索引树页大小。
总之无论怎样,聚集索引和非聚集索引都不推荐在重复度高的字段上建立。

@xingd
很经典。
索引碎片产生的频度如何,多久做一次reorganize,多久一次rebuild
这个我觉得只要到了30%的碎片了就可以做rebuild了,不知道你怎么看?
  回复  引用  查看    
#41楼 2008-01-22 15:34 | xingd      
@PerfectDesign
具体比例要看实际情况了,这个跟fill factor也有关系,肯定是根据业务情况,并且反复调优测试后才能确定合适的值。

微软网站上的推荐值 5%~30% Reorganize 大于30% Rebuild with (Online=ON)
  回复  引用    
#42楼 2008-01-22 16:08 | dfsfsdfsdff [未注册用户]
@cslar
典型的托儿!!!

  回复  引用  查看    
#43楼 2008-01-22 18:06 | PerfectDesign      
@xingd
30%这个数值我忘记是在pest practise还是codesearch里面的微软代码看到的了。

fill factor这个东西一般都没有主张去修改它吧?
能说说要修改它的场景吗?
比如在超大量的增删改环境下指定较大的fill factor?
  回复  引用  查看    
#44楼 2008-01-22 18:21 | xingd      
@PerfectDesign
我也不会主动去设fill factor,仅仅在发现性能问题,比如碎片比例增长很快的时候,考虑fill factor会不会对性能有影响,需不需要做一些调整.

默认的fill factor是0,也就是不预留空间。要对fill factor作调整的时候,肯定要考虑具体的操作对索引的影响,以及rebuild的频率。

可以修改整个数据库的默认fill factor,通常我不会这么做。

index create memory我是从来没动过。

  回复  引用    
#45楼 2008-01-22 23:32 | kevin.xiaoli [未注册用户]
关于从数据索引到谈论asp.net性能上,其实大家可以看下terry.lee推荐的文章:http://www.cnblogs.com/Terrylee/archive/2008/01/14/1038758.html,同时他也介绍了Jeffrey Zhao写的关于性能方面的文章,我个人理解,不是.net不好,而全在开发人员的水平,没有到达那个境界,考虑不到那么多的问题
  回复  引用  查看    
#46楼 2008-01-23 13:33 | 鞠强      
偶的经验是,性能与架构、设计基本无关的,与细节有关。细节要求你对os/db/debug/coding,都要熟悉,越熟悉越好。

比如说,索引那些东西,就要考虑索引的实现机制。网络上总结的那么一坨又一坨的sql编写事项、索引注意事项等,实际上只是表面的东西。理解了原理,你就什么都清楚了,不要背那么多教条了。
  回复  引用  查看    
#47楼 2008-01-23 17:22 | PerfectDesign      
@鞠强
完完全全不同意你的说法。
如果设计都糟糕,那你的项目有无力回天的感觉
如果只是细节,那花点钱找个薪水高的程序员或者找高人做培训,codereview就可以。
微软最佳实践第一条就是首先要设计正确,才能保证数据库的性能。

  回复  引用  查看    
#48楼 2008-01-23 17:46 | xingd      
@PerfectDesign
鞠强的说法某些方面上讲也是对的。好的设计能够保障细节上的优化以较低的成本实行,但架构本身是难以保证效率的,所以我讲的是“架构和技术团队的整体实力”决定了性能。
  回复  引用  查看    
#49楼 2008-01-23 18:11 | PerfectDesign      
@xingd
也许我会错意。
不过我的观点是如果架构不好,性能肯定更糟。
细节做得好,架构不好仍是白搭


  回复  引用  查看    
#50楼 2008-01-23 18:38 | xingd      
@PerfectDesign
"架构不好,性能肯定更糟"这样的说法有点绝对的。

如果只是单台服务器,架构不好的话,但是每个程序员超级牛的话,性能一样很高的。只不过可以维护/重构困难,并且重复的代码比较多。

现代的软件/网站开发,性能绝不是唯一的追求了。
This is footer