请有人帮助我理解为什么标量函数的存在会改变先前索引扫描的估计?
我正在使用 StackOverflow2013 数据库的副本。SQL Server 2019(兼容模式100)
为了演示这个问题,我创建了一个简单的函数,它检查 User.DisplayName 中是否有“s”:
CREATE FUNCTION dbo.IsUserS (@DisplayName nvarchar(80))
RETURNS bit
AS
BEGIN
RETURN CHARINDEX('S', @DisplayName)
END
Run Code Online (Sandbox Code Playgroud)
这是使用该函数的查询:
SELECT U.ID,
U.[DisplayName],
U.[Reputation]
FROM [dbo].[Users] AS [U]
WHERE [U].[CreationDate] > '20100101'
AND [U].[Reputation] > 100
AND dbo.[IsUserS](u.[DisplayName]) = 1
Run Code Online (Sandbox Code Playgroud)
我正在将此查询的计划与完全相同的查询进行比较,但没有函数调用。以下是计划:
https://www.brentozar.com/pastetheplan/?id=ByLy1LlNi
在这两个计划中,我们都从聚集索引扫描开始。对于底部计划(没有过滤器的计划),扫描运算符的估计值与实际值很接近。对于带有过滤器的计划,估计值相差很大(实际行数的 36%)。
我的问题是,为什么 UDF 的存在会改变先前索引扫描的估计?
请注意,我正在 Compat' 模式 100 下运行。如果我翻转到 150,估计值与实际值实际上会更差,除非我打开旧基数估计器(在这种情况下,它与 100 相同,所以仍然很糟糕)。
这里是 SQL 新手,所以很抱歉,如果这是非常基本的东西。
SQL 服务器 2019、Windows
2 个表 - FixingHeader 和 Product
简单查询读取所有固定标头并查找相关产品
select [f].[Id], [f].[FixingHeaderReference], [p].[Description] from [dbo].[FixingHeader] as f
JOIN [Product] AS [p] ON [f].[ProductId] = [p].[Id]
Run Code Online (Sandbox Code Playgroud)
我的 FixingHeader 数据库中只有 7 条记录
看着执行计划,对一些结果感到惊讶。
1 - 为什么计划显示的读取记录多于表本身?
认为这与 3 次处决有关,但为什么是 3 次呢?
2 - 为什么 Product 表使用聚集索引扫描而不是 Seek?正在使用具有索引的主键 ID 读取产品
谢谢!
我是一名数据库学生,我执行了以下查询来同时学习一些内容(LEFT/RIGHT JOIN、UNION、WHERE + RegEx)。令我困扰的是执行顺序。我有两个表,如下所示:
create table practicaleft(
id smallint primary key,
nombre varchar,
cumple date
);
create table practicaright(
id smallint primary key,
apellido varchar,
cumpleanios date
);
Run Code Online (Sandbox Code Playgroud)
然后,我插入一些随机数据:
INSERT INTO practicaleft VALUES
(1, 'John', CURRENT_DATE - 1),
(5, 'Alice', CURRENT_DATE - 5),
(3, 'Bob', CURRENT_DATE - 3),
(7, 'Eva', CURRENT_DATE - 7);
INSERT INTO practicaright VALUES
(5, 'Doe', CURRENT_DATE - 5),
(6, 'Smith', CURRENT_DATE - 6),
(3, 'Johnson', CURRENT_DATE - 3),
(4, 'Brown', CURRENT_DATE - 4);
Run Code Online (Sandbox Code Playgroud)
之后,我执行此查询:
select id, …Run Code Online (Sandbox Code Playgroud) 使用:SQL Server 2008 R2
我目前正在逐步执行查询执行计划,并且遇到了表上聚集索引更新的实例。这里的问题是正在更新的列不是聚集索引的一部分。
桌子:
<table>
id INT IDENTITY(1,1) -- Clustered Index
, name VARCHAR(20) -- Nonclustered Index
, status CHAR(1)
, quantity INT
, price FLOAT
Run Code Online (Sandbox Code Playgroud)
更新声明:
UPDATE a
SET a.status = @status
, a.quantity = @quantity
, a.price = @price
FROM <table> a
WHERE a.name = @name
Run Code Online (Sandbox Code Playgroud)
执行计划显示 Eager Spool 成本为 36%,聚集索引更新成本为 55%,名称索引上的索引查找成本为 9%,计算标量和顶级项目成本为 0%。
为什么计划显示聚集索引更新?我能做些什么来防止这种情况,并防止急切的线轴?
sql-server clustered-index execution-plan sql-server-2008-r2
当我插入具有聚集索引视图的表时,估计的执行计划似乎并行执行表插入和视图的聚集索引插入操作。
下面是一个有点人为的例子。
/*
DROP INDEX [IX__AView] ON [dbo].[_AView]
DROP VIEW _AView
DROP TABLE _A
*/
CREATE TABLE _A (Name VARCHAR(10) NOT NULL)
GO
CREATE VIEW _AView WITH SCHEMABINDING AS
SELECT Name FROM [dbo]._A
GO
CREATE UNIQUE CLUSTERED INDEX [IX__AView] ON [dbo].[_AView] ([Name] ASC)
GO
/*
--run the estimated execution on this
INSERT INTO _A (Name) values ('cheese')
*/
Run Code Online (Sandbox Code Playgroud)

我的查询执行时间过长。请在这里帮助我。
mysql> explain
select pcm.catalog_id
from cat_produ_catal_map_defer pcm, cat_catal_catal_map_defer ccm, cat_catal_defer c
where
pcm.product_id = 2520000
and ccm.catalog_id = pcm.catalog_id
and ccm.parent_catalog_id = 1000025
and levels <> 0
and c.catalog_id = pcm.catalog_id
and c.precedence is not null
order by c.precedence;
+----+-------------+-------+------+--------------------------------------------+----------+---------+------------------------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+--------------------------------------------+----------+---------+------------------------+------+-----------------------------+
| 1 | SIMPLE | c | ALL | idx_1031,idx_17109 | NULL | NULL | NULL | …Run Code Online (Sandbox Code Playgroud) 我一直致力于从我的数据库 (11g) 中的表中获取分页结果。虽然我有一个有效的查询(即结果是正确的),但它的性能不如我希望的那样好,我正在努力提高它的效率(估计仅在该查询上每秒调用 60 次)。
所以首先,我阅读了在 Oracle 中计算页数的有效方法是什么?,并且文章也指出了这一点,但不幸的是,它根本没有讨论所提出的查询的执行计划(我会在星期一看到它们)。
这是我提出的查询(表分区part_code是日期范围):
select <all-columns> from (
select rownum as rnum, <all-columns> from (
select /*+index (my_table index)*/ <all-columns> from my_table
where part_code in (?, ?, ?)
and date between ? and ?
and type in (?, ?, ?)
and func_col1 = ?
/*potentially: and func_col2 = ? and func_col3 = ? ... */
order by date, type, id
)
) where rnum between M and N; /* N-M ~= …Run Code Online (Sandbox Code Playgroud) 我已经创建了一个分区视图为3个表tb_sales2010,tb_sales2011,tb_sales2012使用检查约束(respectivly为每个表)
日期部分(年,[日期])=(2010)
日期部分(年,[日期])=(2011)
日期部分(年,[日期])=(2012)
表 2010 的架构(所有其他表都相同)
CREATE TABLE [dbo].[tb_Sales2010](
[Date] [smalldatetime] NOT NULL,
[ID] [int] NOT NULL
CONSTRAINT [PK_tb_Sales2010] PRIMARY KEY NONCLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[tb_Sales2010] WITH CHECK ADD CONSTRAINT [CK_Date_2010] CHECK ((datepart(year,[Date])=(2010)))
GO
Run Code Online (Sandbox Code Playgroud)
我的查询是
SELECT TOP 1 *
FROM partitionedTb_sales
WHERE DATEPART(YY, DATE) = 2011
Run Code Online (Sandbox Code Playgroud)
我的问题是,执行计划表明它正在扫描所有 3 个表。而不是查看检查约束并说表 …
为一个查询的两次执行捕获了两个实际的查询计划:
计划“快速”花费了大约 1 秒,大约 90% 的时间都会发生。
计划“慢”花了大约 16 秒。
由于图形计划看起来与我相同,因此我转储了 XML 版本并执行了差异以查看文本差异以确保。
快侧有 2 个“SpillToTempDb”警告,慢侧有 4 个警告。看着 2 个额外的慢端:
One SpillToTempDb warning on "Parallelism (Repartition Streams) Cost 1%":
<SpillToTempDb SpillLevel="0" />
On SpillToTempDb warning on "Parallelism (Distribute Streams) Cost 1%":
<SpillToTempDb SpillLevel="0" />
Run Code Online (Sandbox Code Playgroud)
慢速和快速情况下的成本是相同的 (1%)。这是否意味着可以忽略警告?有没有办法显示“实际”时间或成本。那会好很多!对于溢出操作,实际行数是相同的。
除了执行 xml 执行计划的手动文本差异以查找警告中的差异之外,我怎么知道运行时间增加 1500% 的实际原因是什么?
除了“RunTimeCountersPerThread”行之外的差异:
Left file: C:\Users\chrisr\Desktop\fast.sqlplan Right file: C:\Users\chrisr\Desktop\slow.sqlplan
10 <ThreadStat Branches="10" UsedThreads="85">
10 <ThreadStat Branches="10" UsedThreads="73">
------------------------------------------------------------------------
------------------------------------------------------------------------
19 <MemoryGrantInfo SerialRequiredMemory="1536" SerialDesiredMemory="10816" RequiredMemory="124224" DesiredMemory="133536" RequestedMemory="133536" GrantWaitTime="0" GrantedMemory="133536" MaxUsedMemory="105440" />
19 <MemoryGrantInfo …Run Code Online (Sandbox Code Playgroud) 对于以下类型的查询,And如果第一个And条件失败,sql是否会为每个条件处理数据?如果某行的 Emp_ID 不是 12,那么它会检查 Emp_Name 的条件吗?那么SQL是如何处理这种查询的呢?
SELECT [Emp_ID],[Emp_Name],[Emp_Sal] FROM [gyh].[dbo].[Employee_Demo] where Emp_ID='12' And Emp_Name like '%ab%'
Run Code Online (Sandbox Code Playgroud) performance sql-server execution-plan sql-server-2008-r2 query-performance
execution-plan ×10
sql-server ×5
performance ×2
functions ×1
index ×1
mysql ×1
oracle ×1
oracle-11g ×1
postgresql ×1
query ×1
subquery ×1
tempdb ×1