在更短的时间内从表中获取数据

时间:2013-10-04 11:29:16

标签: sql-server sql-server-2008

您好我正在使用SQL Server 2008.在我的数据库中有一个名为MemberBusiness的表。我想从该表中获取数据。

这是我的存储过程

SELECT    BrokerId ,
          RankId ,
          MemberId ,
          InstallmentId ,
          PlanId ,
          IntroducerId ,
          Date ,
          SelfAmount ,
          UnitAmount ,
          SpotAmount ,
          ORBPercentageSelf ,
          ORBPercentageUnit ,
          ORBAmountSelf ,
          ORBAmountUnit ,
          IsSelfBusiness ,
          Mode ,
          InstallmentNo ,
          PlanType ,
          PlanName ,
          CompanyId ,
          CscId ,
          Year ,
          CreateDate ,
          ModifideDate
FROM      dbo.MemberBusiness AS mb
WHERE     ( @CscId = 0
            OR mb.CscId = @CscId
          )
          AND ( @CompanyId = 0
                OR CompanyId = @CompanyId
              )
          AND BrokerId IN ( SELECT    bt.BrokerId
                            FROM      #brokerTable AS bt )
          AND mb.Date >= @StartDate
          AND mb.Date <= @EndDate
          AND mb.RankId >= @FromRankId
          AND mb.RankId <= @ToRankId

MemberBusiness表中,有大约16560352条记录。 SP以上给出了1300条记录,大约需要30秒才能执行,这对我来说是不可接受的。我使用了索引,但仍需要很长时间才能执行。怎么能更快地做到这一点?感谢。

4 个答案:

答案 0 :(得分:0)

一些建议:

  • 摆脱内部选择,取而代之的是这样的内连接:

    SELECT BrokerId,... 来自dbo.MemberBusiness AS mb 将#brokerTable作为bt ON bt.BrokerID = mb.BrokerID加入 在哪里mb.CscID = @CscID ...

  • 那些OR语句可能很慢......你可以摆脱它们或使用不同的查询进行联合吗?

  • 确保您有一个大的单一索引,涵盖您正在比较的所有列,如下所示:

    CREATE INDEX mySearchIndex ON MemberBusiness(CscId ASC,CompanyID ASC,BrokerId ASC,Date ASC,RankId ASC)

答案 1 :(得分:0)

您可以通过多种方式改进查询:

  • 首先,将#brokerTable与内部联接子句链接
  • 您需要避免使用OR子句。由于我不是动态SQL的忠实粉丝,您可以使用IF语句,如下面的showxn,
  • 最后,您需要设计CLUSTERED和NONCLUSTEREd的索引,并使用查询计划测试影响。

SQL:

IF @CscId = 0 AND @CompanyId = 0
BEGIN

    SELECT  mb.BrokerId,
            mb.RankId,
            mb.MemberId,
            mb.InstallmentId ,
            mb.PlanId ,
            mb.IntroducerId ,
            mb.Date ,
            mb.SelfAmount ,
            mb.UnitAmount ,
            mb.SpotAmount ,
            mb.ORBPercentageSelf ,
            mb.ORBPercentageUnit ,
            mb.ORBAmountSelf ,
            mb.ORBAmountUnit ,
            mb.IsSelfBusiness ,
            mb.Mode ,
            mb.InstallmentNo ,
            mb.PlanType ,
            mb.PlanName ,
            mb.CompanyId ,
            mb.CscId ,
            mb.Year ,
            mb.CreateDate ,
            mb.ModifideDate
    FROM    dbo.MemberBusiness AS mb
                INNER JOIN #brokerTable AS bt ON mb.BrokerId = bt.BrokerId
    WHERE mb.Date >= @StartDate
            AND mb.Date <= @EndDate
            AND mb.RankId >= @FromRankId
            AND mb.RankId <= @ToRankId

END
ELSE IF @CscId = 0 AND @CompanyId <> 0
BEGIN

    SELECT  mb.BrokerId,
            mb.RankId,
            mb.MemberId,
            mb.InstallmentId ,
            mb.PlanId ,
            mb.IntroducerId ,
            mb.Date ,
            mb.SelfAmount ,
            mb.UnitAmount ,
            mb.SpotAmount ,
            mb.ORBPercentageSelf ,
            mb.ORBPercentageUnit ,
            mb.ORBAmountSelf ,
            mb.ORBAmountUnit ,
            mb.IsSelfBusiness ,
            mb.Mode ,
            mb.InstallmentNo ,
            mb.PlanType ,
            mb.PlanName ,
            mb.CompanyId ,
            mb.CscId ,
            mb.Year ,
            mb.CreateDate ,
            mb.ModifideDate
    FROM    dbo.MemberBusiness AS mb
                INNER JOIN #brokerTable AS bt ON mb.BrokerId = bt.BrokerId
    WHERE CompanyId = @CompanyId
            AND mb.Date >= @StartDate
            AND mb.Date <= @EndDate
            AND mb.RankId >= @FromRankId
            AND mb.RankId <= @ToRankId

END
ELSE IF @CscId <> 0 AND @CompanyId = 0
BEGIN

    ...

END
ELSE
BEGIN

    ...

END

然后是大部分,索引。您至少需要两个索引:   - 一个群集

CREATE CLUSTERED INDEX [IX_MemberBusiness]
ON [dbo].[MemberBusiness]
(
    RankId,
    Date,
    CompanyId,
    CscId,
    [The real ID of your table]
)
  • 一个非群集

    创建非集群索引[IX_MemberBusiness_nc] ON [dbo]。[MemberBusiness] (     RankId,     日期,     CompanyId,     CscId,     [你桌子的真实身份证] ) 包括 (     [除索引中的所有字段外,所有字段中的字段] )

聚集索引必须包含您在其上进行范围查询的字段(即Date和RankId)。 非聚集必须包括“峰值”数据的字段(即BrokerId,CompanyId,CscId)。就像ids一样。

您可以通过使用SMSS中的查询计划,在索引设计方面做一些工作,方法是测试哪些字段与群集和非群集相关。

这项技术帮助我将项目的性能大幅提升了3倍。

让我知道它是否适合你。

答案 2 :(得分:-1)

可能这些可以帮助朝着正确的方向发展

  1. 查看您的选择查询逻辑
  2. 对于您的sp,使用@searchstring保存搜索字符串的动态参数使查询动态化
  3. 尝试将您的索引设置为@JerSchneid建议。

答案 3 :(得分:-2)

这就是调优和可扩展性。

弗里斯特: 使用查询分析器检查语句并创建索引和统计信息。不要忘记删除未使用的索引。尝试重新排列where子句,以便最佳地访问数据。您还可以使用QA为您创建索引和统计信息。

考虑partitioning the table

如果仍然要慢,请考虑硬件。 找到瓶颈,使用更多内存,更大的CPU或CPU,获得一些SSD,更快的网络。 尝试在群集中共享负载。