我创建了一个标量值函数,它在传入的秒数中暂停。这个函数不会在生产中使用。如果我向查询添加 UDF,我正在尝试测试 SQL Server 如何评估和创建计划。我对它如何评估我的 3 个查询中的最后一个的差异感到非常困惑。首先是创建测试函数的代码:
CREATE FUNCTION dbo.[sleep](@seconds int)
RETURNS datetime
as
BEGIN
DECLARE @sleepUntil datetime
DECLARE @dummy int
SET @sleepUntil = DATEADD(s, @seconds, getdate())
WHILE getdate() < @sleepUntil
SET @dummy = 0
RETURN getdate()
END
Run Code Online (Sandbox Code Playgroud)
现在创建一个表来测试查询
CREATE TABLE #table (num int)
Run Code Online (Sandbox Code Playgroud)
并插入值
INSERT INTO #table
VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9)
Run Code Online (Sandbox Code Playgroud)
第一个查询需要 2 秒才能运行 - 假设 SQL Server 存储从标量函数返回的值,这是有道理的。
SELECT num
FROM #table t
WHERE dbo.sleep(2)=0
Run Code Online (Sandbox Code Playgroud)
第二个仍然需要 2 秒 - 所以我的假设是它也一样。
SELECT num
FROM #table t
WHERE EXISTS (select TOP 1 …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个 SQL 语句,从一个表中提取所有记录并查看它们是否在另一个表中使用。SQL 不是我最擅长的语言,所以我确信这是一个非常简单的查询。这是我的两个表:
tblOrderContracts
--------------------------------------
OrderContractID | bigint
OrderID | bigint
UserContractID | bigint
UserName | varchar
OrderContractDateCreated | datetime
OrderContractStatus | varchar
tblUserContracts
-------------------------------------
UserContractId | bigint
UserName | varchar
UserContractName | varchar
UserContractFileName | varchar
UserContractDateCreated | datetime
UserContractStatus | varchar
Run Code Online (Sandbox Code Playgroud)
用户可以将任意数量的合约应用到一个订单,所以我需要做的是获取所有合约的列表,并查看它们是否按特定顺序使用。现在,我使用子查询来完成工作,但如果不需要,我不喜欢使用子查询。
SELECT uc.UserContractId, uc.UserContractName,
(SELECT oc.OrderID FROM tblOrderContracts as oc WHERE uc.UserContractID =
oc.UserContractID AND oc.OrderID = 466 AND OrderContractStatus =
'Active')
FROM tblUserContracts as uc
WHERE uc.UserName = 'vandel212' AND UserContractStatus = 'Active'
Run Code Online (Sandbox Code Playgroud)
理想情况下,我希望得到一个如下所示的结果集,如果 OrderID …
我有3张桌子。#a是一个主表和两个辅助表,#b并且#c.
create table #a (a int not null, primary key (a asc)) ;
create table #b (b int not null, primary key (b asc)) ;
create table #c (c int not null, primary key (c asc)) ;
insert into #a (a)
select x*10 + y
from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))x(x)
cross join (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9))y(y) ;
insert into #b (b)
select a from #a where a % 5 > 0 ;
insert into #c (c)
select a from #a …Run Code Online (Sandbox Code Playgroud) 我看了一下这个问题:
表达式中的类型转换可能会影响查询计划选择中的“CardinalityEstimate”?
但这与整理有关,而不是与计算列有关。
我在下面的查询中使用了以下表定义,它给了我一个查询提示
表达式中的类型转换 (CONVERT(varchar(10),[t].[FLTCD_FLT_DATE],112)) 可能会影响查询计划选择中的“CardinalityEstimate”
请注意计算列 flightReference
CREATE TABLE [dbo].[repl_Transportation] (
[FLIGHT#] INT NOT NULL,
[FLTCD_FLT_DATE] DATETIME NULL,
[FLTCD_DEP_GATE] CHAR(3) NULL,
[FLTCD_ARR_GATE] CHAR(3) NULL,
[FLTCD_SEQUENCE] CHAR(1) NULL,
[DIRECTION] CHAR(1) NULL,
[PNR_NUMBERS] VARCHAR(70) NULL,
[HK] NUMERIC(3,0) NULL,
[Create_Date] DATETIME NOT NULL,
[Modify_Date] DATETIME NULL,
[flightReference] AS (substring(((CONVERT([varchar](10),[FLTCD_FLT_DATE],
(112))+[FLTCD_DEP_GATE])+[FLTCD_ARR_GATE])+[FLTCD_SEQUENCE],(3),(13))) PERSISTED,
CONSTRAINT [PK_FLIGHT#] PRIMARY KEY CLUSTERED ([FLIGHT#] asc))
IF OBJECT_ID('[dbo].[repl_Transportation_Details]') IS NOT NULL
DROP TABLE [dbo].[repl_Transportation_Details]
GO
CREATE TABLE [dbo].[repl_Transportation_Details] (
[FLT_LEG_ID] INT NOT NULL,
[FLIGHT#] INT NOT NULL,
[LEG_NO] TINYINT …Run Code Online (Sandbox Code Playgroud) sql-server optimization sql-server-2016 computed-column cardinality-estimates
假设我有一个类似的查询:
SELECT *
FROM table_a
JOIN table_b USING (id)
WHERE table_b.column = 1
Run Code Online (Sandbox Code Playgroud)
我有一个索引id和一个索引,column但我经常添加一个复合索引,两者都可以提高这样的查询效率。我的问题是关于索引中列的顺序。通过反复试验,我发现有时 DBMS 更喜欢连接索引,有时它更喜欢WHERE索引。
在上面的查询中,是否有一个硬性、快速的规则可以让我知道哪个键顺序最有效?
通常我只添加两个索引,运行EXPLAIN查询并检查哪个是首选的,然后删除另一个。但是这个过程感觉可以通过更好地理解确定索引顺序所涉及的逻辑来改进。
我有一个麻烦的查询,我们正在尝试调整。我们的第一个想法是采用更大的执行计划的一部分并将这些结果存储到中间临时表中,然后执行其他操作。
我观察到的是,当我们将数据预先准备到临时表中时,执行计划成本会飙升(22 -> 1.1k)。现在,这样做的好处是允许计划并行执行,这将执行时间减少了 20%,但在我们的情况下,每次执行的 CPU 使用率要高得多,这不值得。
我们正在使用带有旧版 CE 的 SQL Server 2016 SP2。
原始计划(成本 ~20):
https://www.brentozar.com/pastetheplan/?id=ry-QGnkCM
原始 SQL:
WITH Object1(Column1, Column2, Column3, Column4, Column5, Column6)
AS
(
SELECT Object2.Column1,
Object2.Column2,
Object3.Column3,
Object3.Column4,
Object3.Column5,
Object3.Column6
FROM Object4 AS Object5
INNER JOIN Object6 AS Object2 ON Object2.Column2 = Object5.Column2 AND Object2.Column7 = 0
INNER JOIN Object7 AS Object8 ON Object8.Column8 = Object2.Column9 AND Object8.Column7 = 0
INNER JOIN Object9 AS Object3 ON Object3.Column10 = Object8.Column11 AND Object3.Column7 = 0
INNER JOIN …Run Code Online (Sandbox Code Playgroud) performance sql-server optimization execution-plan sql-server-2016 query-performance
SELECT something FROM table WHERE primary_key = ?
Run Code Online (Sandbox Code Playgroud)
对比
SELECT something FROM table WHERE primary_key = ? AND other_key = ?
Run Code Online (Sandbox Code Playgroud)
假设这是一个包含other_key不会改变结果集的场景。在实践中第二个查询更快吗?或者,如果提供了多个,数据库是否只使用一个最佳密钥?
SQL Server 2012 优化器不正确。
测试用例,总结:
这是一个简化的测试场景。底部的 DDL 语句。
我有两个用于数据记录的表,A以及B. 有一个 1:n 关系 -A有一个日期时间的标题记录a_time和B详细记录,一个字段B.akey是引用A.id,字段name和(data)。
A 有大约。25,000,000 条记录,B大约有。500,000,000 条记录。B大约有 200 条记录引用A. 一个A和大约。B每五分钟一次插入200条记录,由A.a_time.
聚集索引是主键id,类型为 int 标识。
B有一个非聚集索引,命名IX_B_akey上B.akey。
A.a_time 也被(非聚集)索引。
现在这个查询:
SELECT A.a_time, B.*
FROM B
join A on B.akey = A.id
where
A.a_time > '2017-01-13T01:30:00' and …Run Code Online (Sandbox Code Playgroud) performance sql-server optimization sql-server-2012 query-performance
我正在努力理解执行计划中行估计的来源。
declare
@BatchKey INT = 1, @ParentBatchKey INT = 1,
@QuoteRef varchar(50) = 'Q00018249',
@MpanRef varchar(50) = '1425431100004'
SELECT DISTINCT
ISNULL(c.ContractReference,-1) AS [ContractReference] ,
ISNULL(d_cd.ContractDetailsKey,-1) AS [ContractDetailsKey] ,
-1 AccountManagerKey,
-1 SegmentationKey,
ISNULL(d_tpi.TpiKey,-1) AS [TpiKey] ,
ISNULL(d_cu.CustomerKey,-1) AS [CustomerKey] ,
ISNULL(d_p.ProductKey,-1) AS [ProductKey] ,
-1 as PayPointKey,
-1 AS [GspBandingKey], --Not used in Junifer ESOB
ISNULL(d_pps.[ProductPricingStructureKey],-1) AS [ProductPricingStructureKey],
ISNULL(d_tou.TouBandingKey,-1) AS [PricingStructureBandingKey],
-1 AS [VolumePointCategoryKey],
ISNULL(d_ppc.PowerPeriodCategoryKey,-1) AS [PowerPeriodCategoryKey],
ISNULL(d_pcat.[PriceComponentAggregationTypeKey],-1) AS [PriceComponentAggregationTypeKey],
-1 AS [MarginRateBandingKey], --Not used in Junifer ESOB
-1 …Run Code Online (Sandbox Code Playgroud) sql-server optimization execution-plan sql-server-2014 cardinality-estimates
除了“它发生”之外,我对任何数据库中的查询优化都没有清楚的了解。现在我刚刚看到了一篇“中等”的帖子,它讨论了在优化方面使用 PostgreSQL CTE 的陷阱,因为 CTE 只评估一次,并且任何可能在 CTE 使用方式、数据库方面应用的优化就是不能申请。
但是博客文章中的示例似乎很容易优化 - 即
SELECT * FROM foo WHERE id = 500000;
Run Code Online (Sandbox Code Playgroud)
对比
WITH cte AS (
SELECT * FROM foo
)
SELECT * FROM cte WHERE id = 500000;
Run Code Online (Sandbox Code Playgroud)
如果在第一个要求上懒惰地计算 CTE,那么我可以想象这两个查询可以以相同的方式进行优化(至少我认为)。
这让我想知道...... SQL Server 是否能够比 postgres 更好地优化这样的查询?
数据库之间在优化查询方面的程度/能力是否存在已知差异?
optimization ×10
sql-server ×7
performance ×3
postgresql ×2
cte ×1
functions ×1
index-tuning ×1
join ×1
mysql ×1
subquery ×1