我有 3 个“大”表,它们连接在一对列上(都是ints)。
每个表在Key1、上都有一个聚集索引Key2,然后还有一个列。Key1具有低基数并且非常偏斜。它总是在WHERE子句中被引用。条款中Key2从未提及WHERE。每个连接都是多对多的。
问题在于基数估计。每个连接的输出估计变小而不是变大。当实际结果达到数百万时,这导致最终估计值低至数百。
我有什么办法可以让 CE 做出更好的估计吗?
SELECT 1
FROM Table1 t1
JOIN Table2 t2
ON t1.Key1 = t2.Key1
AND t1.Key2 = t2.Key2
JOIN Table3 t3
ON t1.Key1 = t3.Key1
AND t1.Key2 = t3.Key2
WHERE t1.Key1 = 1;
Run Code Online (Sandbox Code Playgroud)
我尝试过的解决方案:
Key1,Key2join sql-server many-to-many sql-server-2016 cardinality-estimates
我必须从 221+ 百万行表中删除 16+ 百万条记录,而且执行速度非常慢。
如果您分享使以下代码更快的建议,我将不胜感激:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
DECLARE @BATCHSIZE INT,
@ITERATION INT,
@TOTALROWS INT,
@MSG VARCHAR(500);
SET DEADLOCK_PRIORITY LOW;
SET @BATCHSIZE = 4500;
SET @ITERATION = 0;
SET @TOTALROWS = 0;
BEGIN TRY
BEGIN TRANSACTION;
WHILE @BATCHSIZE > 0
BEGIN
DELETE TOP (@BATCHSIZE) FROM MySourceTable
OUTPUT DELETED.*
INTO MyBackupTable
WHERE NOT EXISTS (
SELECT NULL AS Empty
FROM dbo.vendor AS v
WHERE VendorId = v.Id
);
SET @BATCHSIZE = @@ROWCOUNT;
SET @ITERATION = @ITERATION + …Run Code Online (Sandbox Code Playgroud) “SQL 最终子树成本”和“查询时间性能”之间的一般关系是什么?
示例:当优化查询并且它从子树成本 0.2 到 0.1 时,这是否意味着查询时间将快两倍?我在查询中没有看到这种情况。
我们有一个服务器,即使使用“设置统计时间”和“DBCC DROPCLEANBUFFERS”也无法真正衡量查询性能。服务器、事务、程序、后台项目中有不同的进程在进行。
谢谢,
performance database-design sql-server optimization performance-tuning
如何将我的TempDB 数据或日志文件从现在的任何位置移动到不同的驱动器或文件夹?
将表格“展平”成单行的最佳方法是什么?
例如,使用下表:
+-----+-------+-------------+------------------+
| Id | hProp | iDayOfMonth | dblTargetPercent |
+-----+-------+-------------+------------------+
| 117 | 10 | 5 | 0.1400 |
| 118 | 10 | 10 | 0.0500 |
| 119 | 10 | 15 | 0.0100 |
| 120 | 10 | 20 | 0.0100 |
+-----+-------+-------------+------------------+
Run Code Online (Sandbox Code Playgroud)
我想生成下表:
+-------+--------------+-------------------+--------------+-------------------+--------------+-------------------+--------------+-------------------+
| hProp | iDateTarget1 | dblPercentTarget1 | iDateTarget2 | dblPercentTarget2 | iDateTarget3 | dblPercentTarget3 | iDateTarget4 | dblPercentTarget4 |
+-------+--------------+-------------------+--------------+-------------------+--------------+-------------------+--------------+-------------------+
| 10 | 5 | 0.14 | 10 …Run Code Online (Sandbox Code Playgroud) 在这个问题中,我正在使用sys.sysobjects. 但是,提到的答案之一sys.system_objects。我只是想知道这些表之间有什么区别?
sys.objectssys.system_objectssys.sysobjectssysobjects 有更多的东西。
> SELECT count(*) FROM sysobjects;
2312
> SELECT count(*) FROM sys.system_objects;
2201
> SELECT count(*) FROM sys.objects;
> 111
SELECT count(*)
FROM sys.sysobjects
WHERE NOT EXISTS (
SELECT 1
FROM sys.system_objects
WHERE system_objects.object_id = sysobjects.id
);
> 111
Run Code Online (Sandbox Code Playgroud) 在我的数据库中,我有一个带有两个索引的表。出于数据完整性原因,a、b 列上有一个唯一索引 #1。我有另一个索引 #2,其中包含 c、a、b 列,用于性能原因。我注意到这个索引#2 也是唯一的。
在我看来,索引#2 的唯一性似乎是多余的,因为索引#2 中不可能有重复值,而索引#1 中也不可能有重复值。我很想更改索引 #2,使其不再唯一,因为我想象数据库引擎可能会对索引 #2 中的 c、a、b 执行第二次检查,以确保每次插入行时这些列的唯一性,从而导致即使永远不会有重复的值,也会影响性能。它是否正确?
有没有办法删除 a、b 上的索引 #1 并保留 c、a、b 上的索引 #2,但仍然只对 a、b 列施加唯一约束,而不维护两个单独的索引?这将允许我只有一个索引包含所有三列,但仍然对 a、b 强制执行数据完整性约束。为了提高性能,我不需要在 a、b 上建立索引,因为我所有的选择查询都在 where 子句中包含 c 列。这是否是唯一约束而不是索引的用例?我认为数据库引擎基本上以相同的方式对待这两个构造(请参阅这篇文章:何时应该使用唯一约束而不是唯一索引?)。
请记住,索引不是冗余的,但索引的“唯一性”是冗余的。看起来让索引 #2 变得不唯一是理所当然的。但这会带来任何实际的性能提升吗?即使索引 #1 中的列完全包含在索引 #2 中,数据库是否检查两个索引的唯一性?
一些答案询问了用于从此表中选择数据的示例查询。以下是最常见的:
Select [some other columns] from table where c=1 and a=2
Select [some other columns] from table where c=1
Select [some other columns] from table where c=1 and a=2 and b=3
Run Code Online (Sandbox Code Playgroud)
这些查询通常包括选择不在任何索引中的许多其他列。
我们通常不会运行这样的查询:
Select [stuff] from table …Run Code Online (Sandbox Code Playgroud) 每次在索引视图引用的基表中插入、更新或删除数据时,数据库引擎都会自动更新索引视图以反映更改。但是,我不太确定数据库引擎如何更新索引视图。它是否完全重新运行视图中的查询,或者是否使用更有效的方法仅更新相应的部分?
我正在测试一些索引,并希望对哪些索引表现更好(主要是索引中字段的顺序和指定的其他字段)进行一些 AB 测试。
我有正在测试的数据库的备份,但该备份需要很长时间才能恢复。我更希望能够创建索引 foo,收集性能指标,然后删除 foo 以将数据库返回到索引前状态并创建索引 bar。这是索引创建的工作方式,还是索引的创建会以某种方式改变表,而删除索引无法撤消?
我正在尝试将存储过程配置为 EXECUTE AS 具有 sysadmin 权限的用户,以允许非特权用户从未记录的 TVF 获取结果sys.fn_dump_dblog。
我正在作为角色成员创建该过程sysadmin,但是当我随后尝试使用该子句运行该过程时WITH EXECUTE AS SELF,出现以下错误:
消息 9011,级别 14,状态 1,过程 dbo.read_log,第 16 行 [批处理开始第 65 行] 用户无权使用虚拟表 DBLog 查询备份文件。只有 sysadmin 固定服务器角色的成员才有此权限
这对我来说似乎很奇怪,因为我是服务器角色的成员sysadmin,并且WITH EXECUTE AS SELF在过程定义中指定子句应该会导致使用我的用户帐户执行该过程。根据学习网站:
EXECUTE AS SELF 相当于 EXECUTE AS user_name,其中指定的用户是创建或更改模块的人。创建或修改模块的人员的实际用户 ID 存储在 sys.sql_modules 或 sys.service_queues 目录视图的execute_as_principal_id 列中。
如果我WITH EXECUTE AS SELF从过程的定义中删除该子句,TVF 将按预期返回结果。
以下是SQL Server 2019 中的最小、完整且可验证的示例。
首先,证明我们是该sysadmin角色的成员:
USE [master];
GO
SELECT
[roles].[name]
FROM sys.server_principals [members] …Run Code Online (Sandbox Code Playgroud) sql-server ×10
index-tuning ×2
performance ×2
t-sql ×2
datafile ×1
delete ×1
index ×1
join ×1
many-to-many ×1
optimization ×1
permissions ×1
pivot ×1
tempdb ×1