AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 8885
Accepted
Ciaran Archer
Ciaran Archer
Asked: 2011-12-08 07:25:14 +0800 CST2011-12-08 07:25:14 +0800 CST 2011-12-08 07:25:14 +0800 CST

存储过程突然变慢的执行计划

  • 772

我试图了解我们在使用 SQL Server 2000 时遇到的问题。我们是一个中等事务的网站,我们有一个名为的存储sp_GetCurrentTransactions过程,它接受一个客户 ID 和两个日期。

现在,根据日期和客户,此查询可以返回从零到 1000 行的任何内容。

问题:我们所经历的是,Execution Timeout Expired当他们尝试执行该存储过程时,我们会突然为特定客户端收到许多错误(通常或类似)。所以我们检查查询,在 SSMS 中运行它,发现它需要 30 秒。所以我们重新编译存储的 proc 并 -bang- 它现在在 300 毫秒内运行。

我已经和我们的 DBA 谈过这个问题。他告诉我,当我们创建存储过程时,数据库创建了一个查询计划。他说对于那组参数来说这是一个很好的计划,但是如果你给它扔一组参数,那么这个计划就不是那个数据的最佳计划,所以你会看到它运行得很慢。

呈现给我的选项是将问题查询从存储的过程转移到动态 SQL 中,动态 SQL 在每次运行时都会创建执行计划。

这对我来说就像是退后一步,我觉得必须有办法解决这个问题。有没有其他方法来处理这个问题?

任何和所有的回应都表示赞赏。

sql-server stored-procedures
  • 6 6 个回答
  • 15943 Views

6 个回答

  • Voted
  1. Best Answer
    Martin Smith
    2011-12-08T07:34:09+08:002011-12-08T07:34:09+08:00

    这个问题称为参数嗅探。

    更高版本的 SQL Server 为您提供了更多处理它的选项,例如OPTION (RECOMPILE)或OPTIMIZE FOR提示。

    您可以尝试在存储过程中声明变量,将参数值分配给变量并使用变量代替参数,因为这听起来好像大多数时候您都得到了一个相当令人满意的计划。

    通常,最糟糕的计划是那些为具有非常高选择性的参数编译但运行具有低选择性的参数的计划。

    假设使用这种方法生成的计划更健壮并且对所有参数值都满意,那么这种方法相对于 JNK 建议的方法的优势在于它不会为每次调用产生编译成本。

    缺点是,对于某些执行,运行时间可能比专门为这些参数值定制的计划要长,因此这是编译时间与执行时间的权衡。

    • 14
  2. JNK
    2011-12-08T07:35:22+08:002011-12-08T07:35:22+08:00

    除了使用动态 SQL,您总是可以将您的 proc 调用更改为:

    EXEC Database.dbo.usp_Myprocedure 'Parameter' WITH RECOMPILE

    强制(你猜对WITH RECOMPILE了!)执行计划在运行时重新编译。

    您还可以WITH RECOMPILE在存储过程的定义中包含:

    CREATE PROCEDURE usp.MyProcedure (Parameters)
    WITH RECOMPILE
    AS
    ...
    
    • 6
  3. psr
    2011-12-08T09:53:06+08:002011-12-08T09:53:06+08:00

    您也可以尝试决定计划使用哪个数据库,尽管您会与优化器有一点冲突,所以它比您希望的更脆弱。

    该技术是这样的 - 将存储过程分成 2 个,一个用于一组参数,一个用于另一个。将 where 子句添加到每个子句,以便它们之间涵盖所有可能的情况。查看查询计划 - 一个应该针对一组参数进行优化,另一个针对另一组进行优化。您可能必须修改查询才能实现这一点,或者您的查询可能无法实现,在这种情况下,这种方法将不起作用。

    现在让您的原始存储过程检查参数值并分派到上一段中的两个存储过程中的适当一个。

    这可以工作,但它是一种强制优化器更有效地为您的查询工作的技巧。像所有此类黑客攻击一样,在数据库的未来版本中,这可能是不必要的,甚至会使事情变得更糟。因此,即使它有效,您也必须决定是否值得。

    • 2
  4. user606723
    2011-12-08T11:37:40+08:002011-12-08T11:37:40+08:00

    您还可以尝试SET FORCEPLAN索引提示。

    http://msdn.microsoft.com/en-us/library/ms188344.aspx
    它基本上允许您选择加入的顺序。

    您可以使用索引提示来确保 SQL 服务器使用正确的索引。

    • 1
  5. Brian Knight
    2011-12-08T07:39:05+08:002011-12-08T07:39:05+08:00

    嗯...如果我们只关注这个存储过程,我会惊讶于使用缓存的执行计划会导致您看到的问题。我会要求使用一组客户参数和两个日期来查看存储过程的执行计划。我想知道更具体的索引是否会有所帮助-> 例如在 customerId 上,并且只有两个日期?

    • 0
  6. ifx
    2011-12-08T08:25:53+08:002011-12-08T08:25:53+08:00

    突然降低性能听起来像是一个低效的查询计划,可能是由于缺少统计信息。运行设置了“错误和警告”事件类别的 SQL Server 探查器,查看是否有关于缺少统计信息的警告。

    您可能还缺少索引,或者您可能需要对索引进行碎片整理,因为它们可能过于碎片化,SQL Server 无法使用,导致它认为表扫描会产生更少的 I/O。

    @JNK 提出了一个关于存储过程的重要观点——这些是预先编译的,查询计划将与存储过程一起存储。

    我不一定同意使用WITH RECOMPILE,因为这样您就失去了存储和重用查询计划的好处。在某些情况下这是必要的 - 即,如果您在基础表中的分布统计数据在调用之间差异很大,但通常,一旦表中的数据成熟,表中的数据分布将变化最小。

    所以,总结一下:

    1. 检查缺失的统计数据
    2. 检查索引碎片
    3. 创建和使用存储过程
    4. 请重命名过程 - sp_ 是内部系统 SQL Server 过程的软保留前缀命名空间 - 导致 SQL Server 总是首先在主数据库中查找这些存储过程。重命名 proc usp_ 而不是 sp_ 会提高性能,但我怀疑在这种情况下是你的问题。
    • 0

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    您如何显示在 Oracle 数据库上执行的 SQL?

    • 2 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    我可以查看在 SQL Server 数据库上运行的历史查询吗?

    • 6 个回答
  • Marko Smith

    如何在 PostgreSQL 中使用 currval() 来获取最后插入的 id?

    • 10 个回答
  • Marko Smith

    如何在 Mac OS X 上运行 psql?

    • 11 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Marko Smith

    将数组参数传递给存储过程

    • 12 个回答
  • Martin Hope
    Manuel Leduc PostgreSQL 多列唯一约束和 NULL 值 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler 什么时候应该将主键声明为非聚集的? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - 哪个更好作为主键? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick 如何优化大型数据库的 mysqldump? 2011-01-04 13:13:48 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve