对于我们的一个 SQL 服务器,有一个过程会造成阻塞混乱:
大多数情况下,该存储过程在一秒内完成,但不知何故使事务保持打开状态。我从 sp_whoisactive 看到的是 status = sleep 并打开 tran 1 持续大约 5-6 分钟。在这段时间内,出现了起伏的阻塞链。
这个 SP 没有像 BEGIN 和 END TRAN 这样的任何事务。它做了一些基本的 select col,col2,col3.... into #temptables from table1 inner join table 2 ... 然后从 #temptable 中选择
当我们从应用程序检查为什么可能有一个事务保持打开状态时,我正在阅读这些场景以在 SP 本身中使用 XACT ABORT ON。但是当不涉及事务时,XACT ABORT 设置如何在这种情况下提供帮助?
请指教
我有一个针对可以增长到数百万行的表执行的查询。查询来自我们使用的 QA 工具,它超出了数据库的标准功能(就索引的内容以及索引方式和原因而言)。查询是:
SELECT id FROM thisTable t
WHERE col = 'val'
AND ((not exists (SELECT 1 FROM thisTable WHERE refid = t.id) and refbool = 0) or refbool = 1)
ORDER BY newid()
Run Code Online (Sandbox Code Playgroud)
基本上,假设表中有id,refid,refbool,和col列。所以你可以有如下数据:
id | refid | refbool | col
------------------------------------
1 | NULL | 0 | val
2 | NULL | 0 | val
3 | NULL | 0 | val
4 | 2 | 1 | val
5 …Run Code Online (Sandbox Code Playgroud) 我有一个很大的Product表:
| 产品编号 | 产品名称 |
|---|---|
| 1 | 产品一 |
| 2 | 产品二 |
| ... | ... |
| n | 产品编号 |
而 n 大约为 2,000,000。
为了限制某个国家/地区的产品可用性,我有第二个ProductCountryRestriction表:
| 产品编号 | 国家代码 | 包含排除 |
|---|---|---|
| 1 | 美国 | 0 |
| 1 | 英国 | 0 |
| 2 | 澳大利亚 | 1 |
| 2 | 新西兰 | 1 |
如果产品仅限于一个或多个国家/地区,我会将包含产品的国家/地区添加到此表中,其中 IncludeExclude = 0。例如,产品 1 仅适用于美国和英国。
如果产品对除某些国家/地区以外的所有国家/地区都有效,那么我将使用 IncludeExclude = 1 将产品 - 排除的国家/地区添加到此表中。例如,产品 2 适用于除 AUS 和 NZ 之外的所有国家/地区。
与产品对应的所有国家/地区代码必须设置为 IncludeExclude = 0 或 IncludeExclude = 1。不允许混合使用 0 和 1。例如,对于产品 1,有 IncludeExclude = 0 的记录,我无法将 ProductID = 1 和 IncludeExclude = 1 的记录添加到此表中。
该系统的用户可以选择多个国家进行工作。用户首选项存储在UserCountry …
在执行计划之前(因为我正在调试一个运行不佳的计划),我有这个变量赋值块:
DECLARE @Days INT = 180
DECLARE @DateRangeFrom DateTime = DATEADD(d, -@Days, getDate())
DECLARE @DateRangeTo DateTime = getDate()
DECLARE @FacilityID INT = 1010
DECLARE @Answer0 INT = 1879
DECLARE @Answer1 INT = 1949
DECLARE @Answer1SetID INT = 1607
DECLARE @Answer2 INT = 1907
DECLARE @Answer2SetID INT = 1593
Run Code Online (Sandbox Code Playgroud)
我的第一个问题是在 IRItemAnswer_Info 表(节点 ID 19)上执行的查找。它溢出到 Tempdb,它已经以错误的方式开始查询。它引用IRItemAnswerInfo_DGItemID_AnswerSourceID索引,这是正确的索引,因为我正在匹配DGItemID和AnswerSourceID,然后返回IncidentID。索引创建为
CREATE NONCLUSTERED INDEX IRItemAnswerInfo_DGItemID_AnswerSourceID
ON dbo.IRItemAnswer_Info (DGItemID, AnswerSourceID)
INCLUDE([IncidentID], [AnswerBoolean])
Run Code Online (Sandbox Code Playgroud)
但是,查询的估计行数为 53,459,实际行数为 969,812。
我刚刚完成强制通过新的统计数据UPDATE STATISTICS IRItemAnswer_Info …
sql-server execution-plan cardinality-estimates sql-server-2019 query-performance
我使用的应用程序使用 SQL Server 数据库,其中包含许多保存单行配置数据的表,有时在针对更传统的多行表的查询中需要这些表。我见过的大多数代码在处理单个查询时都通过联接访问这些表,但在最近的代码审查中,我看到了一种使用标量子查询的方法,大致如下:
Select T.Id
From dbo.SomeTable T
Where T.SomeValue > (Select Tolerance From dbo.Settings)
Run Code Online (Sandbox Code Playgroud)
虽然它显然有效,但我最初的反应是假设这是对我们标准实践的冒险违反,但我对表单进行了一些实验,发现“子查询返回超过 1 个值。当子查询遵循时,这是不允许的=、!=、<、<=、>、>= 或当子查询用作表达式时”错误。这使得这看起来可以避免意外 1:n 连接带来的不良行为的风险。(在实践中,这不应该是这些单行表的问题,它们相当强大,但我已经看到它出现在系统的其他地方。)
除了(可能非常便宜的)流聚合和断言之外,我的简单测试用例的执行计划看起来非常相似,我认为它们负责查询引擎在多行情况下识别和抛出错误的能力。
使用这种表是否有普遍接受的最佳实践?选择方法时我应该注意哪些主要优点和缺点?
(我知道使用变量来保存数据也是一种选择,但在我们的某些代码中这样做并不总是可行,因此我想重点关注这两种方法和/或任何其他方式的比较将其折叠到单个查询中。)
我有一个经常更新影响某些几何图形的事件的表。几何区域是固定的,但可能有一个事件同时影响多个区域,因此两者之间存在多对多的关系。单个区域也可能同时受到多个事件的影响。
例如:
| 事件ID | 区域编号 |
|---|---|
| 1 | 15 |
| 1 | 31 |
| 2 | 46 |
| 3 | 46 |
| 3 | 55 |
| 4 | 15 |
这些区域在我的表中表示为 ID 值。我需要在空间上表示这些值,因此我需要将这些值连接到包含s 和几何图形的event_id and area_id查找表。area_id不幸的是,这些表位于同一 SQL Server 2014 实例上的两个独立数据库中。
问题是这个连接过程非常慢;返回 18k-24k 行需要 90 秒到 3 分钟不等,具体取决于当前有多少事件处于活动状态。几何查找表包含 84k 行。
事件表结构(为了简单起见,删除了一些附加列):
USE Events_DB;
CREATE TABLE [dbo].[Events](
[EVENTS_ID] [bigint] NOT NULL,
[AREA_ID] [bigint] NOT NULL,
[START_DATE_TIME] [smalldatetime] NULL,
[END_DATE_TIME] [smalldatetime] NULL,
CONSTRAINT [PK_Events] PRIMARY KEY CLUSTERED
(
[EVENTS_ID] ASC,
[AREA_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS …Run Code Online (Sandbox Code Playgroud) sql-server execution-plan spatial sql-server-2014 query-performance
实际计划:https://www.brentozar.com/pastetheplan/? id=SJviG_y1h
我正在寻找有关从哪里开始调整上述存储过程的建议。我们需要它在尽可能接近 1 秒的时间内完成,但目前在生产中最多需要 40 秒。SP 似乎会根据服务器工作负载而波动,因此需要它尽可能高效地运行。在 UAT 没有负载的情况下,针对同一数据库的副本,它在 5 秒内运行。
来自 Brent Ozar 的 sp_blitzcache 的警告包括:并行、计划警告、参数嗅探、隐式转换、函数连接、琐碎计划、未使用的内存授予、最近 4 小时创建的计划、多行表假脱机、非 SARGable
它在 Always On 可用性组数据库的主副本上运行(2 个节点设置,在辅助副本上启用同步提交和只读)。我们无法创建任何额外的索引。
SQL 版本为: Microsoft SQL Server 2017 (RTM-CU29) (KB5010786) - 14.0.3436.1 (X64) Enterprise Edition:Windows Server 2019 Standard 10.0(内部版本 17763:)(虚拟机管理程序)上基于核心的许可(64 位)
其他值得注意的配置:
sql-server availability-groups query-performance performance-tuning
以下查询正确输出搜索、扫描等的数量。我对理解输出中的某些行有疑问。在查询的某些输出行中,索引名称显示为、NULL、、0;而在同一行中,它显示了和/或 的一些非零数字。问题:我们如何解释这些行?index_typeHEAPNumOfSeeksNumOfScansNumOfLookups
备注:所有表都没有聚集索引,因此所有表都是 HEAP。但在以下查询的输出的大多数行中,索引名称都显示(并且不显示为 NULL),并且 index_type 也显示(作为 NONSLUSTER)。因此,问题特定于此评论上面描述的输出行。
参考:sys.dm_db_index_usage_stats。
SELECT OBJECT_NAME(IX.OBJECT_ID) Table_Name
,IX.name AS Index_Name
,IX.type_desc Index_Type
,SUM(PS.[used_page_count]) * 8 IndexSizeKB
,IXUS.user_seeks AS NumOfSeeks
,IXUS.user_scans AS NumOfScans
,IXUS.user_lookups AS NumOfLookups
,IXUS.user_updates AS NumOfUpdates
,IXUS.last_user_seek AS LastSeek
,IXUS.last_user_scan AS LastScan
,IXUS.last_user_lookup AS LastLookup
,IXUS.last_user_update AS LastUpdate
FROM sys.indexes IX
INNER JOIN sys.dm_db_index_usage_stats IXUS ON IXUS.index_id = IX.index_id AND IXUS.OBJECT_ID = IX.OBJECT_ID
INNER JOIN sys.dm_db_partition_stats PS on PS.object_id=IX.object_id
WHERE OBJECTPROPERTY(IX.OBJECT_ID,'IsUserTable') = 1 …Run Code Online (Sandbox Code Playgroud) index sql-server azure-sql-managed-instance query-performance performance-tuning
我有一个 PostgreSQL 表设置作为队列/事件源。
我非常希望保留事件的“顺序”(即使在处理队列项之后)作为 e2e 测试的来源。
我开始遇到查询性能下降的问题(可能是因为表膨胀),并且我不知道如何有效地查询不断变化的键上的表。
Postgres:v15
CREATE TABLE eventsource.events (
id serial4 NOT NULL,
message jsonb NOT NULL,
status varchar(50) NOT NULL,
createdOn timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT events_pkey PRIMARY KEY (id)
);
CREATE INDEX ON eventsource.events (createdOn)
Run Code Online (Sandbox Code Playgroud)
BEGIN; -- Start transaction
SELECT message, status
FROM eventsource.events ee
WHERE status = 'PENDING'
ORDER BY ee.createdOn ASC
FOR UPDATE SKIP LOCKED
LIMIT 10; -- Get the OLDEST 10 events that are pending
-- I …Run Code Online (Sandbox Code Playgroud) 在 Azure SQL 数据库(SQL2019 兼容)上,我有一个 ETL 进程,它以 DeltaTrack 模式填充 HISTORY 表。
在 Proc 中,有一个对 HISTORY 表的更新,查询引擎正在使用 SORT,但我有一个应该覆盖它的索引。
此 UPDATE 的用例是针对现有行,自从该行首次添加到 HISTORY 表中以来,我们已向摄取添加了额外的列。
这种排序会导致我们更大/更宽的表上的更新速度极其缓慢。
如何调整索引或查询以删除查询 3中的排序?
这是根据京东要求更新的 执行计划
这是 DDL。
DROP TABLE IF EXISTS dbo.STAGE;
GO
CREATE TABLE dbo.STAGE
(
Id varchar(18) NULL,
CreatedDate varchar(4000) NULL,
LastModifiedDate varchar(4000) NULL,
LastReferencedDate varchar(4000) NULL,
[Name] varchar(4000) NULL,
OwnerId varchar(4000) NULL,
SystemTimestamp datetime2(7) NULL
)
GO
DROP TABLE IF EXISTS dbo.HISTORY;
GO
CREATE TABLE dbo.HISTORY
(
HistoryRecordId int IDENTITY(1,1) …Run Code Online (Sandbox Code Playgroud) sql-server execution-plan azure-sql-database sort-operator query-performance