我正在测试 sql server 中的合并加入。我有一个INNER JOIN并强制优化器执行以下操作MERGE JOIN:
ID 在个人表中是主键ID 在 Abteilung 表是主键这些表中没有其他索引
select * from [dbo].[Personal] as P inner join [dbo].[Abteilung] as A
on P.[ID]= A.[Personal_ID] OPTION (MERGE JOIN)
Run Code Online (Sandbox Code Playgroud)然后优化器使用这个计划来运行我的查询:
我想强制优化器使用index seek而不是Table Scan
我为实现这个目标做了什么:
ID,上定义分组索引Personal_ID。如果我运行查询,执行计划是这样的变化:这里我有聚集索引扫描,但没有聚集索引搜索
FORCESEEK提示。如果我使用此提示,运行查询会发生错误:由于此查询中定义的提示,查询处理器无法生成查询计划。在不指定任何提示且不使用 SET FORCEPLAN 的情况下重新提交查询。
如果我在查询中添加 where 子句,则查询将更改为:
select * from [dbo].[Personal] as P inner join [dbo].[Abteilung] as A
on P.[ID]= A.[Personal_ID] where A.[Personal_ID]=2
OPTION (MERGE JOIN) …Run Code Online (Sandbox Code Playgroud)在运行Ola 的 IndexOptimize重建所有索引和统计信息后,我立即清除了数据和计划缓存,并运行了一个非常复杂的丑陋查询来获得其性能的基线。查询实际计划显示 ReasonForEarlyTermination=Timeout 和 Est Rows 和 Actual Rows 的偏差(与 est. 相比,实际行因子为 10,000)。
我想知道这种行数的不平衡是否可能是超时的结果 - 我认为在索引和统计信息重建之后应该是合适的?
如果无法更改查询本身,那么优化以 ReasonForEarlyTermination=Timeout 结尾的查询是否有意义?由于我打算做一些索引调整并重新运行查询,所以不是不可能确定可能改进的结果,因为下一个查询计划创建肯定会再次超时,因此可能会有所不同,结果不同?
技术 详细信息:Sql Server 2008 R2 开发。埃德。10.50.6000.34 DB Comp. 80级。
我需要从A包含三个外键的表中找到一个值到另外两个表B和C.
为了实验,我测试了两种查询值的方法:
多个查询:
declare @start int = (select top 1 [Id] from [B] where [Day] = '2015-01-01')
declare @end int = (select top 1 [Id] from [B] where [Day] = '2017-06-14')
declare @category int = (select top 1 [Id] from [C] where [Title] = 'Hello, World!')
select top 1 [Name]
from [A]
where [StartId] = @start
and [EndId] = @end
and [CategoryId] = @category
and [Day] = '2016-05-27'
Run Code Online (Sandbox Code Playgroud)
单个查询:
select top 1 [Name]
from …Run Code Online (Sandbox Code Playgroud) performance sql-server execution-plan sql-server-2012 query-performance
附带的计划运行时间不应超过一分钟,但有时需要数小时。两个外部聚集索引上的 I/O 扫描气球失控,查询爬行。有人可以向我解释为什么会发生这种情况以及如何解决吗?
前段时间我使用了查询提示,但后来意识到大多数时候 SQL Server 比我更聪明。 构建额外的索引/重新组织数据或查询并获得比强制服务器使用计划要好得多的结果这通常效率低下,但对于某些数据子集来说速度足够快。但现在我处于一种我不知道如何更好地组织数据的情况。
我有两张桌子。第一个表 T1 是 (Id, CustomerId),第二个表 T2 具有相同的列。我想在 CustomerId 上加入 T1 到 T2。并获得前 N 行。在这种情况下,优化器看到我只需要 N 个 top 并说,“嘿,我将使用循环并很快找到 N 个匹配项,尤其是当我使用索引查找时。” 但它不起作用,因为没有满足条件的数据。因此它使用 aloop join来连接一个 25m 的表和一个非常慢的 100k 表。
当我强制 SQL Server 使用合并联接时,我得到以下计划,该计划在一秒钟内执行:
我不想强迫它有两个原因:
在这种情况下我该怎么办?
我在 SQL 服务器中有以下查询:
declare @timestamp_start date = getdate() - 1
declare @timestamp_end date = getdate()
SELECT
my_date = a.itemTimestamp
FROM
my_table a with(nolock)
WHERE
(@timestamp_start is null OR a.itemTimestamp >= @timestamp_start)
AND (@timestamp_end is null OR a.itemTimestamp < @timestamp_end)
Run Code Online (Sandbox Code Playgroud)
它非常慢(< 2000 条记录为 90 秒),因为执行计划使用 PK 列的聚集索引作为“my_table”:
为什么会发生这种情况以及如何优化查询性能?
通常这样写很方便:
SELECT *
FROM t1 # ... +many more tables
INNER JOIN t2 ON (t1.id = t2.col)
INNER JOIN t3 ON (t1.id = t3.col)
INNER JOIN t4 ON (t1.id = t4.col)
...
Run Code Online (Sandbox Code Playgroud)
作为带条件的交叉连接:
SELECT *
FROM t1, t2, t3, t4 # ... +many more tables
WHERE
t1.id = t2.col
AND t1.id = t3.col
AND t1.id = t4.col
# +include matches on columns of other tables
Run Code Online (Sandbox Code Playgroud)
但是,交叉连接的简单实现将比内部连接具有更高的时间复杂度。Postgres 是否将第二个查询优化为与第一个查询具有相同时间复杂度的查询?
如果我直接在 SQL Server Management Studio 中执行我的(简单)查询...
SELECT auftrag_prod_soll.ID
FROM auftrag_prod_soll
WHERE auftrag_prod_soll.auftrag_produktion = 51621
AND auftrag_prod_soll.prod_soll_über = 539363
ORDER BY auftrag_prod_soll.reihenfolge
Run Code Online (Sandbox Code Playgroud)
......一切都很好,很快......
Table 'auftrag_prod_soll'. Scan count 2, logical reads 6, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 102 ms.
Run Code Online (Sandbox Code Playgroud)
...因为 SQL Server 会根据两个过滤条件选择合理的执行计划:
另一方面,如果我的应用程序使用游标执行相同的查询......
declare @p1 int
declare @p3 int
set @p3=4
declare @p4 int
set @p4=1 …Run Code Online (Sandbox Code Playgroud) performance sql-server execution-plan cursors query-performance
最近我们开始使用 sp_BlitzCache 来帮助我们调整我们的查询。我们发现一个 SP 有一些问题,我们能够成功地重构它。
在我们调整查询之前的一周内,我有一份 sp_BlitzCache 的输出副本,可在此处获得
https://drive.google.com/open?id=1oiAEl62ZT51qcCEhVzkg8oDA3HB-NCsv
生成此输出的命令运行是
exec sp_BlitzCache @StoredProcName = 'hs_UpdateShipmentPackagesAndWeightSp'
Run Code Online (Sandbox Code Playgroud)
几个问题
1)我注意到我们有多个行用于同一个计划句柄,这是为什么?
2) 您会注意到成本最高的查询 (1451) 具有整个 create procedure 语句的查询文本,这是什么意思?该行的指标是否仅用于创建存储过程?
3) 对于成本最高的行,即上面提到的行,它的最小/最大授权几乎为 2GB。这是否意味着当我们运行 create procedure 语句时,它要求 2gb 的内存?还是在调用 proc 时使用此计划?我想这与问题 2 的答案有关
4) 为什么在某些情况下我们有 Min/Max grant KB > 0 和 Min/Max used grant kb > 0,但百分比内存授权为 null ?
我们正在运行 SQL Server 2012。
谢谢,凯文
我正在将数据从一个数据库归档到另一台 SQL 服务器上的另一个数据库。我们正在我们的数据库中归档多个表。最近我们对源数据库的插入增加了,但归档运行速度不够快。我正在考虑将表的归档拆分为单独的作业,但是我可以做些什么来提高查询的性能。
实际计划中的 QueryTimeStats 如下
+-----------+---------+-------------+---------+
| Statement | CpuTime | ElapsedTime | Percent |
+-----------+---------+-------------+---------+
| 1 | 3 | 3 | 0.00% |
| 2 | 3 | 4 | 0.00% |
| 3 | 0 | 0 | 0.00% |
| 4 | 1 | 1 | 0.00% |
| 5 | 0 | 1 | 0.00% |
| 6 | 1 | 1 | 0.00% |
| 7 | 6 | 6 | …Run Code Online (Sandbox Code Playgroud) execution-plan ×10
sql-server ×9
performance ×4
join ×2
optimization ×2
cursors ×1
datetime ×1
postgresql ×1
statistics ×1
t-sql ×1