c# - 超时过期,优化查询

标签 c# sql-server query-optimization

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

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): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

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 秒!任何提示请解决这个问题。

更新

这是执行计划:

enter image description here

更新2

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

  1. PT.Date 是一个 char(8)(开发人员使用它来开始此项目)(yyyyMMdd)

    <
  2. detailTable 包含 102 列。

最佳答案

尝试这个查询 -

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

关于c# - 超时过期,优化查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18485530/

相关文章:

c# - Linq-to-SQL 实现速度非常慢

sql - 带有 NOT IN 的子查询

sql - Web 服务、Windows 服务或 SQL CLR 集成?

mysql - 减少 MySQL 查询时间(目前已运行 24 小时且仍在继续)

foreach 循环中的 C# foreach

c# - 使用 C++ 向 COM 公开托管事件

c# - 如何在 WP8.1 应用程序中使用反射获取命名空间中的所有类?

c# - MVC4 网站仅适用于一台 PC,不适用于其他 PC,失败并显示 "SQL Network Interfaces, error: 26"

mysql - 如何解释 MySQL EXPLAIN 的输出?

MySQL - 选择列与链接列表中任意位置的条目匹配的行