今天我在兼容级别为80(SQL2000)的数据库中运行在Sql Server 2005 SP2上运行的存储过程时偶然发现了一个有趣的性能问题.
proc运行大约8分钟,执行计划显示索引的使用情况,实际行数为1.339.241.423,比表本身的"实际"实际行数(1.144.640)高出约1000倍,如正确显示估计行数.因此查询计划优化器给出的实际行数绝对是错误的!

有趣的是,当我将proc中的procs参数值复制到局部变量而不是在实际查询中使用局部变量时,一切正常 - proc运行18秒,执行计划显示正确的实际行数.
编辑:正如TrickyNixon所建议的那样,这似乎是参数嗅探问题的一个标志.但事实上,我在两种情况下都完全相同的执行计划.相同的指数以相同的顺序使用.我看到的唯一区别是直接使用参数值时PK_ED_Transitions索引上的实际行数高的方法.
我已经完成了dbcc dbreindex和UPDATE STATISTICS,但没有任何成功.dbcc show_statistics也显示索引的良好数据.
proc是使用RECOMPILE创建的,因此每次运行时都会编译新的执行计划.
更具体一点 - 这个速度很快:
CREATE Proc [dbo].[myProc](
@Param datetime
)
WITH RECOMPILE
as
set nocount on
declare @local datetime
set @local = @Param
select
some columns
from
table1
where
column = @local
group by
some other columns
Run Code Online (Sandbox Code Playgroud)
而且这个版本的运行速度非常慢,但产生完全相同的执行计划(除了使用索引的实际行数太高):
CREATE Proc [dbo].[myProc](
@Param datetime
)
WITH RECOMPILE
as
set nocount on
select
some columns
from
table1
where
column = @Param
group by
some other columns
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?谁知道Sql Server在计算查询计划时从哪里获取实际行计数值? …
sql-server optimization performance stored-procedures sql-execution-plan
我们的生产系统有一个约5秒的查询,但在我们的镜像系统上(尽可能与生产相同)和开发系统需要不到1秒.
我们检查了查询计划,我们可以看到它们有所不同.同样从这些计划中我们可以看出为什么一个人比另一个人服用更长时间.数据,schame和服务器类似,存储过程相同.
我们知道如何通过重新排列的加入,增加提示来解决它,但是此刻它会更容易,如果我们没有做对存储过程(文书)的任何变化.我们还尝试了一个sp_recompile.
什么可能导致两个查询计划之间的差异?
系统:Win2k3 Enterprise上的SQL 2005 SP2 Enterprise
更新:感谢您的回复,结果证明这是统计数据.见下面的摘要.
sql sql-server stored-procedures sql-server-2005 sql-execution-plan
有没有什么好方法可以客观地衡量Oracle 10g中的查询性能?有一个特定的查询,我已经调整了几天.我有一个似乎运行得更快的版本(至少基于我的初始测试),但EXPLAIN的成本大致相同.
我们的网站变得非常困难,所以我们正在考虑优化一些现有的查询.
在研究这个时,我们遇到了几个查询,当查询中有一个简单的聚集索引引用时,执行计划的速度提高了4-5倍...例如
如果这是旧查询:
SELECT ...
FROM myTable
WHERE categoryID = @category
Run Code Online (Sandbox Code Playgroud)
根据SSMS中的执行计划,以下查询将快4倍:
SELECT ...
FROM myTable
WHERE categoryID = @category
AND lotID = lotID
Run Code Online (Sandbox Code Playgroud)
我们似乎无法理解这将如何使查询更快.聚集索引在lotID上,但由于它与自身进行比较,这有什么帮助?
alt text http://img502.imageshack.us/img502/7245/75088152.jpg
我将两个表连接在一起,其中一个是临时表,我在创建表后创建索引.但是在上面的查询执行计划中说.
我应该考虑将所有扫描操作转换为搜索操作?有些部分是连接和条件......
关心bk
我显示一个包含父数据的网格,如果存在相关的子行,则需要显示图标.我的数据库在SQL Server 2008中.让我简化,我有以下两个表 -
订单(PK:ID)
文件(PK:FileID,FK:OrderID)
一个Order可以有零个或多个与之相关的文件.该File表有一个OrderID包含FK引用的列Order.现在,我正在显示一个列出所有内容的网格,Orders我想显示一个图标图像,指示是否Order有任何子行(文件).
这是我尝试过的一种棘手的方法,但不确定它的效率/可扩展性如何 -
SELECT DISTINCT o.ID, o.OrderNum, ...
,(CASE f.ID/f.ID WHEN 1 THEN 1 ELSE 0 END) as FilesExist
...
FROM Order AS o LEFT OUTER JOIN dbo.FileHeader as f ON f.OrderID = o.ID
Run Code Online (Sandbox Code Playgroud)
该CASE声明似乎完全符合要求.如果存在一个或多个文件,它将返回1,否则为0.如果存在多个文件行,那么它将尝试重复Order我添加了DISTINCT的行,我没有选择f.ID但是f.ID/f.ID它将是1 (它存在)和0表示null(不存在).我了解到JOIN比内联SELECT COUNT(*)语句更好.
我已经测试过它可以工作,但我需要专家意见,需要确保这是最好的方法.这是一个非常简单的例子,但我的SELECT陈述很复杂,因为有许多查找,并且它将是一个昂贵的提取,所以我需要确保它的可扩展性.
谢谢.
编辑#1: 总结 - 要么是内部SELECT,要有COUNT(*)
SELECT c.ClaimNo,(SELECT COUNT(*) …Run Code Online (Sandbox Code Playgroud) 对于SQL Server中的即席查询,您不会选择在简单参数化上启用强制参数化的原因是什么?
有性能开销吗?如果是这样,它不会被重复使用的查询计划所产生的(可能的)收益所抵消?
我有3个innodb表,比如说A,B和C.有一个查询可以连接这三个表来生成结果.
SELECT A.a, B.b, C.c
from A
join B on A.id = B.a_id
join C on C.id = B.c_id
where A.a = 'example' and B.b < 10;
Run Code Online (Sandbox Code Playgroud)
在我使用'EXPLAIN'命令测试查询时,它给出了以下顺序:
B - C - A.
但是,这不是最佳的.所以我对所有表运行'ANALYZE TABLE',它给了我:
A - B - C.
,我相信这是正确的顺序.
然后我将SQL部署到生产中,并且无缘无故地,在1个月之后,执行计划切换回坏选项,即B-C-A.在那之后,我尝试了多次ANALYZE TABLE再次运行,但这一次,结果让我感到困惑.有时它也会给我B - C - A,有时它会给我A - B - C,有时甚至是其他执行计划.
所以我的问题是:
在研究Oracle查询解析和性能时,我遇到了以下行为.我使用了以下查询,
SELECT 1
FROM USER_PROCEDURES
WHERE OBJECT_NAME = SUBSTR( UPPER('Client_Sys.Clear_Info' ), 1, INSTR( UPPER('Client_Sys.Clear_Info'), '.' ) - 1 )
AND PROCEDURE_NAME = SUBSTR( UPPER('Client_Sys.Clear_Info' ), INSTR( UPPER('Client_Sys.Clear_Info' ),'.' ) + 1 )
UNION
SELECT 1
FROM USER_OBJECTS
WHERE OBJECT_NAME = UPPER('Client_Sys.Clear_Info')
AND OBJECT_TYPE = 'PROCEDURE';
Run Code Online (Sandbox Code Playgroud)
上述查询的解释计划如下,

现在我将查询更改为以下格式[交换SELECT语句],
SELECT 1
FROM USER_OBJECTS
WHERE OBJECT_NAME = UPPER('Client_Sys.Clear_Info')
AND OBJECT_TYPE = 'PROCEDURE'
UNION
SELECT 1
FROM USER_PROCEDURES
WHERE OBJECT_NAME = SUBSTR( UPPER('Client_Sys.Clear_Info' ), 1, INSTR( UPPER('Client_Sys.Clear_Info'), '.' ) - 1 )
AND PROCEDURE_NAME …Run Code Online (Sandbox Code Playgroud) 我正在优化长时间运行的T-SQL查询.不知何故,我记得SQL Server中有一个功能,它允许检查索引存在时计划的方式.有点像CREATE VIRTUAL INDEX然后检查计划.但我没有找到如何实现这一目标.
SQL Server 2008R2中是否有这样的功能?
sql ×5
sql-server ×5
indexing ×3
performance ×3
join ×2
oracle ×2
explain ×1
mysql ×1
optimization ×1
oracle10g ×1
parent-child ×1
ssms ×1