我有两个类似的查询,它们生成相同的查询计划,只是一个查询计划执行了 1316 次聚集索引扫描,而另一个执行了 1 次。
两个查询之间的唯一区别是不同的日期标准。长时间运行的查询实际上更窄了日期条件,并拉回了更少的数据。
我已经确定了一些对这两个查询都有帮助的索引,但我只想了解为什么 Clustered Index Scan 操作符在一个查询上执行 1316 次,而这个查询实际上与它执行 1 次的查询相同。
我查看了正在扫描的PK的统计数据,它们是相对最新的。
原始查询:
select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
select incident_id as exported_incident_id
from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-06-01 00:00:00.000' and '2011-07-01 00:00:00.000'
and exported_incidents.exported_incident_id is not null
Run Code Online (Sandbox Code Playgroud)
生成这个计划:

缩小日期范围标准后:
select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
select incident_id as exported_incident_id
from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000' …Run Code Online (Sandbox Code Playgroud) 在优化一些存储过程时,我与 DBA 坐下来讨论了一些具有高阻塞和/或高读/写活动的存储过程。
DBA 提到的一件事是我应该TABLE在存储过程的顶部声明所有变量(尤其是变量)以避免重新编译。
这是我第一次听说这个,并且在重新访问我们拥有的所有不同存储过程之前正在寻找一些确认。他称其为“延迟查看代码”,而重新编译正在锁定将导致阻塞的模式。
将所有变量声明移到存储过程的顶部是否会减少重新编译?
sql-server stored-procedures optimization sql-server-2008-r2
我试图了解我们在 SQL Server 2000 中遇到的一个问题。我们是一个中等事务性的网站,我们有一个名为的存储过程sp_GetCurrentTransactions,它接受一个客户ID和两个日期。
现在,根据日期和客户,此查询可以返回从零到 1000 行的任何内容。
问题:我们所经历的是,Execution Timeout Expired当特定客户端尝试执行该存储过程时,我们会突然收到许多错误(通常或类似的错误)。所以我们检查了查询,在 SSMS 中运行它,发现它需要 30 秒。所以我们重新编译存储的 proc 并且 -bang- 它现在在 300 毫秒内运行。
我已经和我们的 DBA 谈过了。他告诉我,当我们创建存储过程时,数据库创建了一个查询计划。他说对于那组参数是一个很好的计划,但是如果你向它抛出一组特定的参数,那么该计划将不是该数据的最佳计划,因此你会看到它运行缓慢。
提供给我的选项是将问题查询从存储过程移回动态 SQL,在每次运行时都会创建执行计划。
这对我来说就像是后退了一步,我觉得必须有办法解决这个问题。有没有其他方法来处理这个问题?
任何和所有的回应表示赞赏。
OFFSET ... FETCHSQL Server 2012 引入的新模型提供了简单且快速的分页。考虑到这两种形式在语义上相同且非常常见,为什么会有任何差异?
人们会假设优化器可以识别两者并将它们(简单地)优化到最大程度。
这是一个非常简单的案例,OFFSET ... FETCH根据成本估算,速度提高了约 2 倍。
SELECT * INTO #objects FROM sys.objects
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY object_id) r
FROM #objects
) x
WHERE r >= 30 AND r < (30 + 10)
ORDER BY object_id
SELECT *
FROM #objects
ORDER BY object_id
OFFSET 30 ROWS FETCH NEXT 10 ROWS ONLY
Run Code Online (Sandbox Code Playgroud)

可以通过创建 CIobject_id或添加过滤器来改变此测试用例,但不可能消除所有计划差异。OFFSET ... FETCH总是更快,因为它在执行时做的工作更少。
sql-server optimization execution-plan sql-server-2012 offset-fetch
当我写这样的查询时......
select *
from table1 t1
join table2 t2
on t1.id = t2.id
Run Code Online (Sandbox Code Playgroud)
SQL 优化器,不确定这是否是正确的术语,是否将其转换为...
select *
from table1 t1, table2 t2
where t1.id = t2.id
Run Code Online (Sandbox Code Playgroud)
本质上,SQL Server 中的 Join 语句只是一种更简单的编写 sql 的方法吗?或者它实际上是在运行时使用的?
编辑:我几乎总是,而且几乎总是,使用 Join 语法。我只是好奇会发生什么。
我正在使用 SQL Server 2008 R2 并且我有这个伪查询 (SP):
select ...
from ...
WHERE @LinkMode IS NULL
AND (myColumn IN (...very long-running query...))
...
...
Run Code Online (Sandbox Code Playgroud)
问题是查询需要很长时间才能执行——即使我使用@LinkMode=2.
正如您所注意到的,只有当 @LinkMode 为 null 时才应该执行长时间运行的查询,而这里不是这种情况。在我的情况下 @LinkMode = 2 !
但是,如果我将其更改为:
select ...
from ...
WHERE 1=2
AND (myColumn IN (...very long time exeted query...))
...
...
Run Code Online (Sandbox Code Playgroud)
SP确实跑得很快。
我以前听说有时优化器可以优化标准的顺序。
所以我问:
即使优化器选择了不同的路由,还有什么比检查 if 更快=null?我的意思是,我认为检查if a==null是多比正在运行的其他长的查询速度更快...
如何强制SQL Server 按照我编写的方式运行查询(相同的顺序)?
我运行一个EXPLAIN:
mysql> explain select last_name from employees order by last_name;
+----+-------------+-----------+------+---------------+------+---------+------+-------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+-------+----------------+
| 1 | SIMPLE | employees | ALL | NULL | NULL | NULL | NULL | 10031 | Using filesort |
+----+-------------+-----------+------+---------------+------+---------+------+-------+----------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
我表中的索引:
mysql> show index from employees;
+-----------+------------+---------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | …Run Code Online (Sandbox Code Playgroud) 下面更新
我有一个具有典型帐户/父帐户体系结构的帐户表来表示帐户层次结构(SQL Server 2012)。我使用 CTE 创建了一个 VIEW 来散列层次结构,总的来说它工作得很好,而且符合预期。我可以查询任何级别的层次结构,并轻松查看分支。
有一个业务逻辑字段需要作为层次结构的函数返回。每个帐户记录中的一个字段描述了企业的规模(我们将其称为 CustomerCount)。我需要报告的逻辑需要从整个分支汇总 CustomerCount。换句话说,给定一个帐户,我需要将该帐户的 customercount 值与层次结构中帐户下方每个分支中的每个子项相加。
我使用 CTE 中构建的层次结构字段成功计算了该字段,该字段看起来像 acct4.acct3.acct2.acct1。我遇到的问题只是让它运行得很快。如果没有这个计算字段,查询会在大约 3 秒内运行。当我添加计算字段时,它变成了一个 4 分钟的查询。
这是我能想出的最好的版本,它返回正确的结果。我正在寻找有关如何在不牺牲性能的情况下重新构建此视图的想法。
我理解这个变慢的原因(需要在 where 子句中计算一个谓词),但我想不出另一种方法来构造它并且仍然得到相同的结果。
下面是一些示例代码,用于构建表并执行 CTE,这与它在我的环境中的工作方式几乎完全一样。
Use Tempdb
go
CREATE TABLE dbo.Account
(
Acctid varchar(1) NOT NULL
, Name varchar(30) NULL
, ParentId varchar(1) NULL
, CustomerCount int NULL
);
INSERT Account
SELECT 'A','Best Bet',NULL,21 UNION ALL
SELECT 'B','eStore','A',30 UNION ALL
SELECT 'C','Big Bens','B',75 UNION ALL
SELECT 'D','Mr. Jimbo','B',50 UNION ALL
SELECT 'E','Dr. John','C',100 UNION ALL
SELECT 'F','Brick','A',222 UNION …Run Code Online (Sandbox Code Playgroud) 我正在尝试确定哪些索引用于带有WHERE条件的 SQL 查询,GROUP BY而当前运行速度很慢。
我的查询:
SELECT group_id
FROM counter
WHERE ts between timestamp '2014-03-02 00:00:00.0' and timestamp '2014-03-05 12:00:00.0'
GROUP BY group_id
Run Code Online (Sandbox Code Playgroud)
该表目前有 32.000.000 行。当我增加时间范围时,查询的执行时间会增加很多。
有问题的表如下所示:
CREATE TABLE counter (
id bigserial PRIMARY KEY
, ts timestamp NOT NULL
, group_id bigint NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
我目前有以下索引,但性能仍然很慢:
CREATE INDEX ts_index
ON counter
USING btree
(ts);
CREATE INDEX group_id_index
ON counter
USING btree
(group_id);
CREATE INDEX comp_1_index
ON counter
USING btree
(ts, group_id);
CREATE INDEX comp_2_index
ON counter …Run Code Online (Sandbox Code Playgroud) postgresql performance index optimization postgresql-9.3 query-performance
我有Address一个名为 的表,它有一个名为 的持久计算列Hashkey。该列是确定性的,但不精确。它有一个不可查找的唯一索引。如果我运行这个查询,返回主键:
SELECT @ADDRESSID= ISNULL(AddressId,0)
FROM dbo.[Address]
WHERE HashKey = @HashKey
Run Code Online (Sandbox Code Playgroud)
我得到这个计划:

如果我强制索引,我会得到更糟糕的计划:

如果我尝试同时强制索引和查找,则会出现错误:
由于此查询中定义的提示,查询处理器无法生成查询计划。在不指定任何提示且不使用的情况下重新提交查询
SET FORCEPLAN
这仅仅是因为它不精确吗?我以为坚持就无所谓了?
有没有办法在不使其成为非计算列的情况下使该索引可查找?
有没有人有任何有关此信息的链接?
我无法发布实际的表创建,但这里有一个具有相同问题的测试表:
drop TABLE [dbo].[Test]
CREATE TABLE [dbo].[Test]
(
[test] [VARCHAR](100) NULL,
[TestGeocode] [geography] NULL,
[Hashkey] AS CAST(
( hashbytes
('SHA',
( RIGHT(REPLICATE(' ', (100)) + isnull([test], ''), ( 100 )) )
+ RIGHT(REPLICATE(' ', (100)) + isnull([TestGeocode].[ToString](), ''), ( 100 ))
)
) AS BINARY(20)
) PERSISTED
CONSTRAINT [UK_Test_HashKey] UNIQUE NONCLUSTERED([Hashkey])
)
GO
DECLARE @Hashkey …Run Code Online (Sandbox Code Playgroud) index sql-server optimization sql-server-2012 computed-column
optimization ×10
sql-server ×8
index ×3
cte ×1
explain ×1
innodb ×1
join ×1
mysql ×1
offset-fetch ×1
performance ×1
postgresql ×1
t-sql ×1