有如下数据表tb_Product:productId int
productName nvarchar(250)
Model nvarchar(80)
displayRank int
productPicture nvarchar(100)
brand nvarchar(50)
keyWords nvarchar(150)
mainSpecification nvarchar(100)
price nvarchar(50)
pagerRank0 int 现在productName上建立了全文索引,现在需要编写一个基于全文索引的搜索排序并分页的T-SQL语句(存储过程)
排序时,需要根据表中pagerRank0字段的值和全文索引中表示匹配度的rank的值的进行乘积后按乘积后的值的大小进行排序并分页显示。现在tb_product表中有60万的信息,每次根据productName进行全文搜索时可能会返回几百甚至几万条纪录,因此每次查询都要花费比较常的时间(15秒左右),我编写的分页代码如下:
求第一页的前16条纪录:
select top  16 f.RANK * p.pagerRank0 AS ranks, p.* FROM FREETEXTTABLE([tb_product], (productname), 'caps') AS f RIGHT OUTER JOIN tb_product AS p ON f.[KEY] = p.productId WHERE f.RANK > 0 and isPassAudit='true' ORDER BY ranks DESC求第三页的代码如下:
SELECT * FROM (SELECT ROW_NUMBER() OVER(ORDER BY f.RANK * p.pagerRank0 DESC) AS rownum, f.RANK * p.pagerRank0 AS ranks, p.* 
                 FROM FREETEXTTABLE([tb_product], (productname), 'caps') AS f RIGHT OUTER JOIN tb_product AS p ON f.[KEY] = p.productId WHERE f.RANK > 0  and isPassAudit='true') AS D 
                  where rownum BETWEEN 33 AND 48 ORDER BY d.ranks DESC现在主要的问题是:在显示第一页数据时时需要全文检索整个表,因此速度比较慢,但显示其它页时,由于数据已经缓存到内存中,因此速度就很快了,因此请高手能否先解决第一页速度慢的问题?是否能对我写的T-SQL进行优化。

解决方案 »

  1.   

    呵呵。期望高手能来解决啊,本来我想把整个表都缓存到内存中,这样性能也该有很大提升的,但运行
    EXEC sp_tableoption 'tb_product','pintable', 'true'
    后再通过
    Select ObjectProperty(Object_ID('tb_product'),'TableIsPinned') 查看,发现还是没有把整个表都缓存到内存,谁能知道该怎么把整个数据表都缓存到内存吗
      

  2.   

    to  fredrickhu:不会吧,您该是个高手啊,挂了这么多的勋章,排名都已在100以内了啊。请出手帮小弟我一把啊
      

  3.   

    现在我想了一个方法:就是先搜索符合需要的productid和ranks两个字段纪录,并把这些纪录保存到内存数组中,然后在内存中进行排序,最后根据排序后的结果再去搜索数据库中的相应纪录,这样应该可以大幅度提高性能,因为排序的工作是在内存中完成的。因此我编写了如下T-SQL:DBCC DROPCLEANBUFFERS 
    DBCC FREEPROCCACHE 
    go
    select  f.RANK * p.pagerRank0 AS ranks, p.productid FROM FREETEXTTABLE([tb_product], (productname), 'tools') AS f  right JOIN tb_product AS p ON f.[KEY] = p.productId WHERE f.RANK > 0系统返回4000条左右的纪录,但尽然要耗时7秒钟!不知道高手能否帮忙优化一下,在tb_product表中对productid进行了聚集索引(主键自增)。
      

  4.   

    EXEC sp_tableoption 'tb_product','pintable', 'true' 只驻留表中已被读取或修改的页的吧,当读取其它新页时继续驻留,而不是执行过后就马上全表驻留。语句上没什么可优化的地方,你需要用rank值做为因子来排序。
      

  5.   

    关键你躲不开FREETEXTTABLE,这是个函数
      

  6.   

    你测试下select *
    into #temp
    from FREETEXTTABLE([tb_product], (productname), 'caps') as f
    WHERE f.RANK > 0  
    需要多长时间,如果时间不多,可以考虑分开操作,再连接排序
      

  7.   

    谢谢您的方法。我测试一下。但还有一个问题:若有多个用户同时查询时是否会有冲突?因为大家都用了临时表temp,就会涉及到多个用户同时往临时表中插入和删除数据啊
      

  8.   

    不会,#temp只对当前连接有效,也就是说,不同连接可以都使用#temp,互不影响
      

  9.   

    根据您的方法我测试了一下,数据到临时表的时间是2S,但现在的问题是在临时表中只有rank和productid的信息,还要根据临时表中productid字段信息从tb_productid中获取所有的纪录,然后再把两个表的信息进行合并,最后根据临时表的rank值和tb_product中的pagerrank0的值进行乘积并倒序排列才能得到我要的结果。这个如何能快速实现呢?