-2

您好我正在使用 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

4 回答 4

0

A couple suggestions:

  • Get rid of that inner select, instead make it an inner join like this:

    SELECT BrokerId, ... FROM dbo.MemberBusiness AS mb JOIN #brokerTable as bt ON bt.BrokerID=mb.BrokerID WHERE mb.CscID=@CscID...

  • Those OR statements could be slow... can you get rid of them or do a union with a different query?

  • Make sure you have a big single index that covers all of the columns you're comparing like this:

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

于 2013-10-04T11:37:41.903 回答
0

您有很多方法可以改进您的查询:

  • 首先,将您的#brokerTable 与内部连接子句链接,
  • 您需要避免使用 OR 子句。由于我不是动态 SQL 的忠实拥护者,您可以使用下面的 showxn 之类的 IF 语句,
  • 最后,您需要设计索引,包括 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]
)
  • 一个非集群

    CREATE NONCLUSTERED INDEX [IX_MemberBusiness_nc] ON [dbo].[MemberBusiness] (RankId, Date, CompanyId, CscId, [您的表的真实 ID]) INCLUDE ([选择中的所有字段,索引中的字段除外])

聚集索引必须包含您进行范围查询的字段(即日期和排名 ID)。非集群必须包含“峰值”数据的字段(即 BrokerId、CompanyId、CscId)。就像身份证一样。

您需要在索引设计上做一些工作,通过使用 SMSS 中的查询计划测试集群和非集群中哪个字段相关。

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

请让我知道这对你有没有用。

于 2013-10-04T12:04:40.940 回答
-1

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

  1. 为您的选择查询逻辑创建一个视图
  2. 对于您的 sp,使用@searchstring包含您的搜索字符串的动态参数使查询动态化
  3. 尝试使您的索引像@JerSchneid 建议的那样。
于 2013-10-04T11:40:24.307 回答
-2

这都是关于调优和可扩展性的。

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

考虑对表进行分区

如果它仍然很慢,请考虑硬件。找到瓶颈并使用更多 RAM、更大的 cpu 或 cpu,获得一些 SSD,更快的网络。尝试在集群中分担负载。

于 2013-10-04T11:42:51.103 回答