我们有一个在 VMware 虚拟机中运行的 SQL Server 2016 SP1 实例。它包含 4 个数据库,每个数据库用于不同的应用程序。这些应用程序都在单独的虚拟服务器上。它们都没有在生产中使用。不过,测试应用程序的人报告了性能问题。
这些是服务器的统计信息:
用户通过基于 C++ 的 ERP 应用程序执行单屏幕访问。
当我ostress使用许多小查询或大查询对 Microsoft 的 SQL Server 进行压力测试时,我获得了最大性能。唯一的限制是客户端,因为他不能足够快地回答。
但是当几乎没有任何用户时,SQL Server 几乎不做任何事情。然而,人们必须永远等待才能在应用程序中保存任何内容。
根据 Paul Randal 的“告诉我它在哪里受到伤害”查询,所有等待事件中有 50% 是ASYNC_NETWORK_IO.
这可能意味着网络问题,或应用程序服务器或客户端的性能问题。他们甚至都没有以最大能力远程使用他们的资源。大多数情况下,所有机器(客户端、应用程序服务器、数据库服务器)上的 CPU 都在 26% 左右。
网络连接的延迟约为 1-3 毫秒。数据库服务器的 IO 在应用程序正常使用期间的最大写入速度为 20MB/s(平均为 7-9MB/s)。当我进行压力测试时,我的速度最高可达 5GB/s。
缓冲区缓存大小为我们的 ERP 系统 DB 为 60GB,我们的财务软件为 20GB,质量保证软件为 1GB,文档归档系统为 3GB。
我授予 …
我在同一台服务器上有两个 SQL Server 实例:
sp_configure 结果在两个实例上相同(新的 2016 选项除外)。
我在同一个磁盘文件夹上的两个实例上创建了新数据库。自动生长参数相同。
自动创建和自动更新统计选项被关闭。
然后我做了一个测试,将 10000 次插入到一个堆中:
set nocount on
go
create table dbo.TestInsert ( i int not null, s varchar(50) not null )
declare @d1 datetime, @d2 datetime, @i int
set @d1 = getdate()
set @i = 1
while @i <= 10000
begin
insert into dbo.TestInsert ( i, s ) select @i, …Run Code Online (Sandbox Code Playgroud) 在我目前的环境中,我正在与 NOLOCK 作斗争。我听到的一个论点是锁定的开销会减慢查询速度。所以,我设计了一个测试来看看这个开销可能有多少。
我发现 NOLOCK 实际上减慢了我的扫描速度。
起初我很高兴,但现在我很困惑。我的测试以某种方式无效吗?NOLOCK 实际上不应该允许稍微快一点的扫描吗?这里发生了什么事?
这是我的脚本:
USE TestDB
GO
--Create a five-million row table
DROP TABLE IF EXISTS dbo.JustAnotherTable
GO
CREATE TABLE dbo.JustAnotherTable (
ID INT IDENTITY PRIMARY KEY,
notID CHAR(5) NOT NULL )
INSERT dbo.JustAnotherTable
SELECT TOP 5000000 'datas'
FROM sys.all_objects a1
CROSS JOIN sys.all_objects a2
CROSS JOIN sys.all_objects a3
/********************************************/
-----Testing. Run each multiple times--------
/********************************************/
--How fast is a plain select? (I get about 587ms)
DECLARE @trash CHAR(5), @dt DATETIME = SYSDATETIME()
SELECT @trash …Run Code Online (Sandbox Code Playgroud) 我正在努力理解为什么行估计如此错误,这是我的情况:
简单联接 - 使用 SQL Server 2016 sp2(sp1 上的相同问题),dbcompatibity=130。
select Amount_TransactionCurrency_id, CurrencyShareds.id
from CurrencyShareds
INNER JOIN annexes ON Amount_TransactionCurrency_id = CurrencyShareds.Id
option (QUERYTRACEON 3604, QUERYTRACEON 2363);
Run Code Online (Sandbox Code Playgroud)
SQL 估计 1 行,而它是 107131 并选择执行嵌套循环(链接到计划)。在 CurrencyShareds 上更新统计信息后,估计就可以了,并选择合并连接(链接到新计划)。只要将一条记录添加到 CurrencyShareds,统计信息就会变得“陈旧”并且 sql 返回错误估计。
我不会太担心这个简单的查询,但这只是更大查询的一部分,这是多米诺骨牌的开始......
为什么在 100 条记录表中添加一行会导致这样的损坏?在查看基数估计跟踪的输出时,我看到了这个警告,***WARNING: badly-formed histogram ***但我找不到关于这个主题的更多信息。
以下是基数估计的完整输出:
Begin selectivity computation
Input tree:
LogOp_Join
CStCollBaseTable(ID=1, CARD=107131 TBL: annexes)
CStCollBaseTable(ID=2, CARD=100 TBL: CurrencyShareds)
ScaOp_Comp x_cmpEq
ScaOp_Identifier QCOL: [test.MasterData].[dbo].[CurrencyShareds].Id
ScaOp_Identifier QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id
Plan for computation:
CSelCalcExpressionComparedToExpression( QCOL: [test.MasterData].[dbo].[Annexes].Amount_TransactionCurrency_id x_cmpEq …Run Code Online (Sandbox Code Playgroud) performance sql-server sql-server-2016 cardinality-estimates query-performance
我有一个存储过程:
当我(数据库所有者)运行这个过程时,一切都按预期工作。当我的同事通过 Active Directory 中的角色对该数据库具有 DROP/CREATE 权限时,会出现一些问题。令我困惑的是:
表的创建没有dbo在名称前显式指定架构。这导致domain\cowork_id.table_name_here创建一个名为table 的表。除了在他的个人模式中创建的表之外,他现在还在数据库中拥有该模式(在运行 proc 之前它不存在)。
发生了什么?为什么 SQL Server 在用户架构中创建表而不是在dbo未指定时创建表?
是否有关于 SQL Server 2016 中关于如何估计包含 SUBSTRING() 或其他字符串函数的谓词的基数的更改的任何文档或研究?
我问的原因是我正在查看一个在兼容模式 130 下性能下降的查询,原因与与包含对 SUBSTRING() 调用的 WHERE 子句匹配的行数估计值的变化有关。我通过查询重写更正了这个问题,但我想知道是否有人知道有关 SQL Server 2016 中该领域更改的任何文档。
演示代码如下。在这个测试案例中,估计值非常接近,但准确度因数据而异。
在测试用例中,在兼容级别 120 中,SQL Server 似乎使用直方图进行估计,而在兼容级别 130 中,SQL Server 似乎假定表的固定 10% 匹配。
CREATE DATABASE MyStringTestDB;
GO
USE MyStringTestDB;
GO
DROP TABLE IF EXISTS dbo.StringTest;
CREATE TABLE dbo.StringTest ( [TheString] varchar(15) );
GO
INSERT INTO dbo.StringTest
VALUES
( 'Y5_CLV' );
INSERT INTO dbo.StringTest
VALUES
( 'Y5_EG3' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_NE' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_PQT' );
INSERT INTO …Run Code Online (Sandbox Code Playgroud) sql-server optimization substring sql-server-2016 cardinality-estimates
我制作了一个脚本,一次一个,从数据库中删除所有外键,就像这样:
ALTER TABLE MyTable1 DROP CONSTRAINT FK_MyTable1_col1
ALTER TABLE MyTable2 DROP CONSTRAINT FK_MyTable2_col1
ALTER TABLE MyTable2 DROP CONSTRAINT FK_MyTable2_col2
Run Code Online (Sandbox Code Playgroud)
让我感到惊讶的是脚本需要很长时间:平均每个 DROP FK 需要 20 秒。现在,我明白创建 FK 可能是一件大事,因为服务器必须去检查 FK 约束是否从一开始就没有被侵犯,而是下降了?当丢弃需要这么长时间的 FK 时,服务器会做什么?这既是为了我自己的好奇心,也是为了了解是否有办法让事情变得更快。能够删除 FK(不仅仅是禁用它们)将使我在迁移过程中更快,从而最大限度地减少停机时间。
我有一个非常大的地理LINESTRING数据表,我要从 Oracle 移动到 SQL Server。在 Oracle 中有许多针对此数据执行的评估,并且它们也需要针对 SQL Server 中的数据执行。
问题:SQL Server 对有效的要求LINESTRING比 Oracle更严格;“LineString 实例不能在两个或多个连续点的间隔内重叠”。 碰巧我们的LINESTRINGs的百分比不符合该标准,这意味着我们需要评估数据的函数失败。我需要调整数据,以便它可以在 SQL Server 中成功验证。
例如:
验证一个非常简单的LINESTRING自我加倍:
select geography::STGeomFromText(
'LINESTRING (0 0 1, 0 1 2, 0 -1 3)',4326).IsValidDetailed()
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)24413: Not valid because of two overlapping edges in curve (1).
MakeValid针对它执行函数:
select geography::STGeomFromText(
'LINESTRING (0 0 1, 0 1 2, 0 -1 3)',4326).MakeValid().STAsText()
Run Code Online (Sandbox Code Playgroud)
Run Code Online (Sandbox Code Playgroud)LINESTRING (0 -0.999999999999867, 0 0, 0 0.999999999999867)
不幸的是,该MakeValid函数更改了点的顺序并删除了第三维,这使我们无法使用它。我正在寻找另一种无需重新排序或删除第三维即可解决此问题的方法。
有任何想法吗?
我的实际数据包含数百/数千个点。
通过在此处阅读此LIKE 字符长度限制,看起来我无法在 LIKE 子句中发送超过 ~4000 个字符的文本。
我正在尝试从特定查询的查询计划缓存中获取查询计划。
SELECT *
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) AS qp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) AS st
where st.text like '%MY_QUERY_LONGER_THAN_4000_CHARS%' ESCAPE '?'
Run Code Online (Sandbox Code Playgroud)
如果里面的查询LIKE超过 4000 个字符,那么即使我的查询在缓存计划中,我也会得到 0 个结果。(我期待至少有一个错误)。
有没有办法解决这个问题或采取不同的方式?我有可能是 >10000字符长的查询,看起来我无法通过LIKE.
我在4个vCPU VM运行Microsoft SQL Server 2016 SP2-CU6(13.0.5292.0)与max degree of parallelism设置为2和cost threshold for parallelism设置为50。
早上,当我尝试显示SELECT TOP 100查询的估计执行计划时,我遇到了大量等待,并且呈现估计计划的操作需要几分钟,通常在 5 到 7 分钟的范围内。同样,这不是查询的实际执行,这只是显示Estimated Execution Plan 的过程。
sp_WhoIsActive将显示PAGEIOLATCH_SH等待或LATCH_EX [ACCESS_METHODS_DATASET_PARENT]等待,当我在操作期间运行Paul Randal 的 WaitingTasks.sql脚本时,它显示CXPACKET等待,工作线程显示PAGEIOLATCH_SH等待:
*资源描述字段= exchangeEvent id=Port5f6069e600 WaitType=e_waitPortOpen waiterType=Coordinator nodeId=1 tid=0 ownerActivity=notYetOpened waiterActivity=waitForAllOwnersToOpen
工作线程看起来将整个stats表带入内存(因为这些页码以及从 Paul Randal 的查询点显示的后续页码指向stats表的聚集键)。一旦计划确实回来了,即使在我看到stats缓存中的大部分表损耗,只剩下各种记录(我认为由于类似查询的搜索操作而被拉出)之后,它在当天剩余时间内基本上是即时的。
如果查询实际上是使用使用 SCAN 运算符的计划执行的,我会期望这种初始行为,但是为什么在评估执行计划时这样做只是为了到达上面链接的计划中所示的 SEEK 运算符?我可以做些什么(除了在办公时间之前运行此语句以便适当缓存我的数据)来帮助提高性能?我假设一对覆盖索引将是有益的,但它们真的能保证行为的任何变化吗?我必须在此处处理一些存储和维护窗口限制,并且查询本身是从供应商解决方案生成的,因此此时欢迎任何其他建议(除了更好的索引)。
sql-server ×10
sql-server-2016 ×10
performance ×4
foreign-key ×1
like ×1
optimization ×1
spatial ×1
substring ×1
t-sql ×1
vmware ×1