【问题标题】:Timeout expired, optimize query超时过期,优化查询
【发布时间】:2013-08-31 09:16:51
【问题描述】:

我有这个查询来获取两个日期之间账单的所有详细信息:

SELECT DT.* 
FROM DetailTable DT, BillTable BT, PackageTable PT
WHERE PT.Id = BT.IdPackage 
  AND DT.IdBill= BT.Id 
  AND PT.CodeCompany = @codeCompany
  AND PT.Date BETWEEN @begin and @end

每个包裹都有很多账单,我想获取公司账单的详细信息, 数据库中的结果只有 20,000,但我有:

System.Data.SqlClient.SqlException (0x80131904):超时。这 在操作完成之前经过的超时时间或 服务器没有响应。

c#代码:

using (SqlConnection sqlConn = new SqlConnection(SqlServerMasterConnection))
{
  if (sqlConn.State != ConnectionState.Open) sqlConn.Open();
  using (SqlCommand cmd = new SqlCommand("select DT.* from DetailTable DT, BillTable BT, PackageTable PT where  PT.Id= BT.IdPackage and DT.IdBill= BT.Id and  PT.CodeCompany = @codeCompany and PT.Date between @begin and @end",
                            sqlConn))
  {
    cmd.Parameters.Add(new SqlCeParameter(@begin , beginDate));
    cmd.Parameters.Add(new SqlCeParameter("@end", endDate));
    cmd.Parameters.Add(new SqlCeParameter("@codeCompany", codeCompany));
    using (DbDataReader reader = cmd.ExecuteReader())
    {
        while (reader.Read())
        {
           //work todo
        }
    }
  }
}

我什至在 SQL Server Management 中尝试过这个需要 25 秒!任何提示请解决这个问题。

更新

这是执行计划:

更新2

对于这个问题我有两个问题(我想要你的想法)。

  1. PT.Date 是一个char(8)(开发者使用它来启动这个项目)(yyyyMMdd)

  2. detailTable 包含 102 列。

【问题讨论】:

  • 使用正确的连接。这是 2013 年
  • 请添加您的执行计划。也许你只需要在你的表上添加一些索引。
  • @Devart,添加执行计划,我用Id作为主键自增,和外键的关系
  • 请问,您需要从DetailTable 的所有列中获取数据吗?如果否,则添加包含列的非聚集索引。
  • @Devart,是的,我必须获取所有列

标签: c# sql-server query-optimization


【解决方案1】:

试试这个查询 -

SELECT DT.*
FROM dbo.DetailTable DT
WHERE EXISTS(
    SELECT 1
    FROM dbo.BillTable BT
    JOIN (
        SELECT PT.Id
        FROM dbo.PackageTable PT
        WHERE PT.CodeCompany = @codeCompany
            AND PT.Date BETWEEN @begin AND @end 
    ) PT ON PT.Id = BT.IdPackage
    WHERE DT.IdBill = BT.Id 
)

另一种方式——

CREATE PROCEDURE dbo.usp_Test1
      @codeCompany VARCHAR(50)
    , @begin DATETIME
    , @end DATETIME
AS
BEGIN

    IF OBJECT_ID (N'tempdb.dbo.#temp') IS NOT NULL
    DROP TABLE #temp

    CREATE TABLE #temp (ID BIGINT PRIMARY KEY)

    INSERT INTO #temp (ID)
    SELECT BT.Id
    FROM dbo.BillTable BT
    JOIN dbo.PackageTable PT ON PT.Id = BT.IdPackage
    WHERE PT.CodeCompany = @codeCompany
    AND PT.[Date] BETWEEN @begin AND @end 

    SELECT DT.*
    FROM dbo.DetailTable DT
    WHERE DT.IdBill IN (SELECT Id FROM #temp)

END

【讨论】:

  • 第一个结果相同(24 秒),但 PROCEDURE 只有 7 秒,我不想使用它,我会让它作为我的最后一个解决方案,(谢谢你的回答)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-14
  • 1970-01-01
  • 1970-01-01
  • 2020-05-27
  • 1970-01-01
相关资源
最近更新 更多