浏览模式: 普通 | 列表
1

?当我们把几个表的某些字段抽取出来,然后用union all创建出一个view时,我们总希望这些表的索引能够在针对视图的查询时有效。很久以前,我凭着对sql server的SQL自动优化的超级相信,想当然地以为它能够做到这点。但是sql2000让我失望并且痛苦了一回。

?假设我们有这样的两个表
?X(a,b) Y(a)
?在X上有分别针对a和b建立的索引IX_X_a,和IX_X_b,在Y上有索引IX_Y_a

接下来我们构造一个这样的 view(V)

select a,b from X
union all
select a,a from Y

然后我们对这样的两个查询进行分析:
1、select * from V where a = @s
2、select * from V where b = @s

看看执行计划,发现什么了吗? 对,在查询2中很悲惨地对Y表进行了全表扫描! 当Y表的数据越来越大,这个查询的速度就会越来越慢,缺少SEEK的下场可想而知。而据说,这个问题在sql2005中得到了解决,我们只能对现在仍不敢使用的2005再多一份期盼了。

那么在2000中我们无法去解决这个问题呢,放弃使用view?不行,这个view被大量多次地使用。使用分区视图?也不行,分区视图指的是这些用到的字段必须是相同。其实分区视图和2005的分区表是有些类似的。而此场景下的X,Y表完全是两个不同的东西(实际上X还有很多列,Y也还有很多列)。

我的解决方法就是对Y表增加一个b列,让它的值等于a,首当其冲的就是使用计算列了,formula为[a],再对视图查询看看,OK了,两个索引都会被利用到了。但是问题还是有的,在接下来的合并复制(Merge Replication)中,我遇到了意料不到的错误(此是后话,按下不表)!!! 所以我现在使用了trigger来做这件事,在insert时update b = a。

除了复制,这个视图仍然不够聪明,我实际上的视图大概是这样的:
select 'X' as type,a,b from X
union all
select 'Y' as type,a,b from Y

当我使用查询如下时
select * from V where type = 'X' and a = @s

SQL2000并不会聪明地只去对X表查询,它仍然对X,Y两个表都进行了索引上的SEEK操作,要知道,实际使用的这个V我union了8个表啊,这样操作时间就是8*T! 有人说了,在这个V上建立索引吧,这样可以时间减少到3+T了,事实上我尝试了这个操作,但后来我放弃了,VIEW上能够创建索引的前提条件太多了,我无法满足它,所以最终,我依然在8*T的日子中继续我的生活....

sql server 合并复制(Merge Replication)

[ 2006-04-23 22:46:08 | 作者: progame ]
sql server的复制(replication)真是会让人头疼,尤其是数据结构改变后的同步

先说一下如何单向同步,在代理属性中第二步的run agent中通过加命令参数exchangetype来改变,1为uploading,表示只从订阅者上传到发布者,2为downloading,表示只从发布者更新到订阅者,3为bidirectional,表示双向同步,即默认的同步方式。

如果在数据库结构改变后继续同步,可以使用取消同步之前生成的sql脚本一次运行(但我怀疑这样是有问题的),前提是包括订阅脚本一起运行,否则的话就必须在订阅时选择初始化结构和数据,因为不然的话,会报说发布的数据库中没有唯一的rowguidcol,我就奇怪了,为什么不能在没有任何订阅者的情况下做一个快照,这样的话就会自动添加这个列了。

因为我们更新数据库结构时,会将rowguidcol这个列给删除的,这样就导致我下一次再建立同步时又得初始化所有的订阅者,然而我并不希望publisher的数据都更新到subscriber,使用行过滤的办法的话我又得对每个subscriber做不同的发布,这真是一个难题。

解决方法,在建立数据库时,添加属性rowguidcol的列,并且设置唯一性索引,在订阅时,选择订阅数据库已有架构和数据,这样就不会把订阅端的数据冲掉了,但前提是publisher和subscriber的对应同一主键的rowguidcol的值要一样,否则更新时会导致冲突。

可能的改进

[ 2006-04-22 23:04:06 | 作者: progame ]
1、感觉一个在线的html editor是需要的,但是一直找不到合适的 (已经完成)
问题仍然存在,在IE下undo redo居然又无效了,FireFox下面的insertcode无法将class带入
2、guestbook修改为针对每个user的留言(已经完成)
3、对链接的设置提供一个不需要直接书写html的方法
4、不允许修改发布时间 (已经完成)
5、改进分页处理(原来的LBS是select all,然后根据recordcount来判断多少页,再使用absolutepage来取所需的页)
6、已经加入了自动保存的功能(每分钟以及页面关闭时)

LBS程序结构剖析

[ 2006-04-18 21:38:34 | 作者: progame ]
有一点写一点,方便其它想修改的人。

LBS整个结构使用了MVC的三层架构,在LBS文件夹下的是view,class下的是model,source下的是controller,就是V来生成页面HTML,C下对传入的参数进行处理,然后决定要使用什么样的view,M相当于active record,有字段属性,以及和数据库交互。

MVC的架构给LBS的修改带来了相当的便利,当然如果不清楚这种结构可能会对多个asp文件协同工作跳来跳去感觉迷糊。

另外LBS的一大特色就是缓存的处理,页面加载时最先加载的是_common.asp,在这里会new一个lbsCache,然后从application中读取缓存,如果存在,则直接使用,否则loadfromdb,当然在load后会在application中存入。

因为使用了缓存,所以在数据变化时就必须同步缓存,所以用UpdateGlobalCounter以及在保存article时的重新loadArticles,保存comment时重新loadComment....等一系列的同步处理。

缓存的处理都是在class/cache.asp中完成的,这是LBS的一个重点文件,另一个就是global.asp,这个文件处理了sidebar、pageheader、pagefooter的输出,所以如果要在siderbar中增加panel,在这里修改就行了。

default.asp是用来处理所有和文章列表的展现,展现方式分两种(mode=list和mode=normal),可以自己处理其它的参数传入,比如说cat=?,user=?,tab=?,这样就可以做用户的首页,TAG的查看,Archive的列表。

如何设置聚集索引(Cluster Index)

[ 2006-04-16 12:01:17 | 作者: progame ]
在blog的修改中,我对几个表的主键进行了删除,使用唯一索引代替,从而把宝贵的聚集索引机会让给其它更需要的索引。

聚集索引的好处就是可以让数据按照此索引的顺序进行物理位置存放,用blog_Comment表来说明,此表有
comm_id
comm_logid
comm_author
comm_posttime等字段

comm_id是自增ID,唯一性索引,如果让它做主键的话,那么聚集索引也默认是它了。但是我们知道comm_id的增长顺序和postime是一致的,可是我们在批量取数据时,是否会用这样一个顺序区间来过滤呢?

比如说posttime between DATE1 and DATE2,OK这样的话聚集索引利用到了,因为这个区间段的数据是非常亲密地靠在一起的,可以用最少的I/O开销取得所需的结果集。可是我们知道,更多的时候我们是在显示一个article时然后读取它的所有comments,这时,过滤条件就成了comm_logid = ID了,如果聚集索引被comm_id心安理得地占用的话,那么很可能我们这批comments需要多个数据页才能得到,这样的话,就大大地增加了时间,因为I/O的开销比CPU在内存上的数据查找排序都是要高一个数据级的。

但是聚集索引的改变同样会给其它的查询带来负面影响,比如说comm_id = ID的查询,在原来只需要在PK_blog_Comment_comm_id的聚集索引上查找记录,然后得到的指针指向就是实际数据块的存放位置了,但是现在,在此非聚集的唯一索引上查找得到的指针是指向IX_blog_Comment_comm_logid的的位置,所以需要多一次的Bookmark Lookup才能取得所需数据。

其实使用的方法很简单,当你需要频繁地取得批量数据时,把聚集索引放在最有可能定位区间的字段上。

另外blog_Article的聚集索引我放在posttime上了,因为经常要对此字段进行order by的查询,虽然logid和posttime的排序方向是一样的,但是我这样可能通过cluster index的lookup 节省一个order by的时间,不过到底孰优孰劣我还不敢下结论。

其它的blog_Archive,blog_Category的聚集索引都在authorid上,因为这个都是对于authorid = ID的查询。

也许随着数据量的增长,情况会有不同,这个以后再看情况调整了。

做了一些小的更新

[ 2006-04-12 23:07:35 | 作者: progame ]
1、更友好的user_name.html和tag_name.html
2、archive
3、related articles
4、url rewrite
同时修复了一些小的bug以及添加了索引

----------------------------------------------------
2006-04-16

终于有每个用户自己的skin 和 title了
其它还有很多小的修改

暂时先就这样吧

[ 2006-04-09 20:32:09 | 作者: progame ]
终于还是找了这个小巧的LBS架设了,因为修改了一些东西,所以大致看代码都看了一下,真是佩服ASP程序能写得如此精妙,美中不足的对于缓存的处理还是不能很令人满意。

修改如下:
1、迁移到MSSQLSERVER(索引仍未建立,反正不急),虽然LBS对绝大多数的数据访问和参数值处理进行了封装,但仍有漏网之鱼
2、加了Activated Users,用来显示最后一段时间活跃的用户列表,并按发表数排序
3、加入Tag list,用来对日志进行更好的分组(相当于用户自已建立category和一个log属于多个category)。
4、在Cache的categories中加入一个id为0的UnCategoried的对象(相当于null object模式了),这样可以不必强行每个日志都要放入分类了
5、注册的一些限制都取消了,比如说等待10s,用户名长度,密码长度....
6、对验证码加入了一些额外的模糊处理,并且修改为登录的用户在回复时不需要输入验证码
7、点击用户链接时显示用户的日志列表,而不是原来的用户信息

为了节省时间,对于tag的处理都是通过触发器实现的,所以说不可能回退到access了

本来还想改的:
每个用户可以有自己的skin, title , sidebar content,不过这个工程量太大,没时间弄
1