Questions tagged «query-performance»

有关改善数据库查询的性能和/或效率的问题。

1
SQL Server-处理嵌套的非确定性视图堆栈中的字符串本地化
在对数据库进行概要分析时,我遇到了一个视图,该视图引用了一些不确定性函数,对于该应用程序池中的每个连接,每分钟可访问1000-2500次。从视图中看,一个简单的代码将产生以下执行计划:SELECT 对于少于一千行的视图来说,这似乎是一个复杂的计划,每隔几个月可能会看到一两行发生变化。但是随着以下其他情况的恶化,情况变得更糟: 嵌套视图是不确定的,因此我们无法为其编制索引 每个视图都引用多个UDFs来构建字符串 每个UDF都包含嵌套UDF的,以获取本地化语言的ISO代码 堆栈中的视图使用从s 返回的其他字符串构建器UDF作为JOIN谓词 每个视图堆被视为一个表,这意味着有INSERT/ UPDATE/ DELETE在每个触发器来写入底层表 在视图上,这些触发器使用CURSORS该EXEC存储过程作为参考更多的这些串建设UDF秒。 这对我来说似乎很烂,但是我只有几年使用TSQL的经验。它也会变得更好! 看来开发人员认为这是个好主意,做了所有这些工作,以便所存储的几百个字符串可以基于从UDF特定于模式的a返回的字符串进行翻译。 这是堆栈中的视图之一,但是它们都同样糟糕: CREATE VIEW [UserWKStringI18N] AS SELECT b.WKType, b.WKIndex , CASE WHEN ISNULL(il.I18NID, N'') = N'' THEN id.I18NString ELSE il.I18nString END AS WKString ,CASE WHEN ISNULL(il.I18NID, N'') = N'' THEN id.IETFLangCode ELSE il.IETFLangCode END AS IETFLangCode ,dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, …

6
a = 0和b = 0以及…z = 0与a + b + c + d = 0的性能
这是一个简单的问题,我似乎找不到答案。 在性能方面,如果我有WHERE诸如这样的子句a=0 and b=0 and ... z=0,如果我用替换该条件,我会获得任何性能a+b+...+z=0吗? 换句话说,通过替换以下内容,可以提高性能吗? Select * From MyTable Where A=0 and B=0 and C=0 and D=0... 用 Select * From MyTable Where A+B+C+D=0... 我知道它可以依赖于索引,但是为此,我们只说不存在索引。算术运算符(+)的性能是否优于“或”或“与”逻辑运算符? 我的印象是,加法的效果要好于使用AND或OR的多个条件。 检测结果 在420万行的表上 返回行,其中A = 0 B = 0和C = 0-> 351748行 加法(A + B + C = 0)花费了5秒,而逻辑条件A = 0且B = …

3
SQL Server中的巨大数据和性能
我已经编写了一个带有SQL Server后端的应用程序,该应用程序可以收集和存储大量记录。我已经计算出,在高峰时,平均记录量约为每天3亿4千万(运行20小时)。 我的原始解决方案(在完成数据的实际计算之前)是让我的应用程序将记录插入到客户查询的同一张表中。显然,该崩溃和烧毁很快,因为不可能查询插入了这么多记录的表。 我的第二个解决方案是使用2个数据库,一个用于应用程序接收的数据,另一个用于客户端就绪的数据。 我的应用程序将接收数据,将其分块成约10万条记录,然后批量插入到临时表中。在记录约100k之后,应用程序将即时创建另一个具有与以前相同的架构的登台表,然后开始插入该表中。它将在作业表中创建一条记录,该表的名称具有100k条记录,并且SQL Server端的存储过程会将数据从登台表移至可用于客户端的生产表,然后删除表由我的应用程序创建的临时表。 除了具有Jobs表的登台数据库之外,两个数据库都具有相同模式的5个表的相同集合。暂存数据库在将要存储大量记录的表上没有完整性约束,键,索引等。如下所示,表名称为SignalValues_staging。目的是让我的应用程序尽快将数据装入SQL Server。动态创建表以便轻松迁移表的工作流程效果很好。 以下是我的登台数据库中的5个相关表以及我的作业表: 我编写的存储过程负责处理所有登台表中的数据并将其插入生产环境。以下是我的存储过程的一部分,该过程从登台表插入生产环境: -- Signalvalues jobs table. SELECT * ,ROW_NUMBER() OVER (ORDER BY JobId) AS 'RowIndex' INTO #JobsToProcess FROM ( SELECT JobId ,ProcessingComplete ,SignalValueStagingTableName AS 'TableName' ,(DATEDIFF(SECOND, (SELECT last_user_update FROM sys.dm_db_index_usage_stats WHERE database_id = DB_ID(DB_NAME()) AND OBJECT_ID = OBJECT_ID(SignalValueStagingTableName)) ,GETUTCDATE())) SecondsSinceLastUpdate FROM SignalValueJobs …

2
T-SQL查询使用完全不同的计划,具体取决于我要更新的行数
此问题是从Stack Overflow 迁移而来的,因为可以在Database Administrators Stack Exchange上回答。 迁移 7年前。 我有一个带有“ TOP(X)”子句的SQL UPDATE语句,而我要更新值的行大约有40亿行。当我使用“ TOP(10)”时,我得到一个几乎立即执行的执行计划,但是当我使用“ TOP(50)”或更大时,查询永远不会完成(至少在我等待时)。它使用完全不同的执行计划。较小的查询使用一个非常简单的计划,该计划带有一对索引查找和一个嵌套循环联接,其中完全相同的查询(UPDATE语句的TOP子句中的行数不同)使用的方案涉及两个不同的索引查找,表假脱机,并行性以及其他一系列复杂性。 我已经使用“ OPTION(USE PLAN ...)”来强制它使用由较小查询生成的执行计划-当我这样做时,我可以在几秒钟内更新多达100,000行。我知道查询计划是好的,但是SQL Server仅在只涉及少量行的情况下才会自行选择该计划-更新中任何相当大的行数都会导致次优计划。 我以为应该归咎于并行性,所以我MAXDOP 1对查询进行设置,但是没有任何效果-这一步骤已经过去,但是糟糕的选择/性能却没有。我也sp_updatestats今天早上跑了,以确保不是这个原因。 我已经附上了两个执行计划-计划越短也越快。此外,这是有问题的查询(值得注意的是,无论行数是大还是小,我包含的SELECT似乎都是快速的): update top (10000) FactSubscriberUsage3 set AccountID = sma.CustomerID --select top 50 f.AccountID, sma.CustomerID from FactSubscriberUsage3 f join dimTime t on f.TimeID = t.TimeID join #mac sma on f.macid = …

5
在T-SQL中使用IF会削弱还是破坏执行计划的缓存?
此问题是从Stack Overflow 迁移而来的,因为可以在Database Administrators Stack Exchange上回答。 迁移 7年前。 有人向我建议,在t-SQL批处理中使用IF语句会降低性能。我试图找到一些确认或验证此断言。我正在使用SQL Server 2005和2008。 断言是以下批处理: IF @parameter = 0 BEGIN SELECT ... something END ELSE BEGIN SELECT ... something else END SQL Server无法重新使用生成的执行计划,因为下一次执行可能需要其他分支。这意味着SQL Server将基于执行当前可以确定需要哪个分支的基础,从执行计划中完全消除一个分支。这是真的吗? 另外在这种情况下会发生什么: IF EXISTS (SELECT ....) BEGIN SELECT ... something END ELSE BEGIN SELECT ... something else END 无法提前确定执行哪个分支的地方?

3
强制流量不同
我有一张这样的桌子: CREATE TABLE Updates ( UpdateId INT NOT NULL IDENTITY(1,1) PRIMARY KEY, ObjectId INT NOT NULL ) 本质上跟踪ID不断增加的对象的更新。 该表的使用者将选择一个由100个不同的对象ID组成的块,这些ID UpdateId由一个特定的并从其开始UpdateId。从本质上讲,跟踪它停止的位置,然后查询任何更新。 我发现这是一个有趣的优化问题,因为我只能通过编写恰好由于索引而做我想要做的查询的查询来生成一个最大最优查询计划,但不能保证我想要的: SELECT DISTINCT TOP 100 ObjectId FROM Updates WHERE UpdateId > @fromUpdateId @fromUpdateId存储过程参数在哪里。 有以下计划: SELECT <- TOP <- Hash match (flow distinct, 100 rows touched) <- Index seek 由于UpdateId正在使用对索引的查找,因此结果已经不错,并且可以按照我想要的那样从最低更新ID到最高更新ID进行排序。这会生成一个流程明确的计划,这正是我想要的。但是排序显然不能保证行为,所以我不想使用它。 此技巧还导致了相同的查询计划(尽管具有冗余的TOP): …

2
默认约束,值得吗?
我通常按​​照以下规则设计数据库: 除db_owner和sysadmin外,其他任何人都不能访问数据库表。 用户角色在应用程序层进行控制。我通常使用一个db角色来授予对视图,存储过程和函数的访问权限,但是在某些情况下,我添加了第二条规则来保护某些存储过程。 我使用TRIGGERS最初验证关键信息。 CREATE TRIGGER <TriggerName> ON <MyTable> [BEFORE | AFTER] INSERT AS IF EXISTS (SELECT 1 FROM inserted WHERE Field1 <> <some_initial_value> OR Field2 <> <other_initial_value>) BEGIN UPDATE MyTable SET Field1 = <some_initial_value>, Field2 = <other_initial_value> ... END DML使用存储过程执行: sp_MyTable_Insert(@Field1, @Field2, @Field3, ...); sp_MyTable_Delete(@Key1, @Key2, ...); sp_MyTable_Update(@Key1, @Key2, …

1
单行INSERT…SELECT比单独的SELECT慢得多
给定以下堆表,该堆表具有从1到400编号的400行: DROP TABLE IF EXISTS dbo.N; GO SELECT SV.number INTO dbo.N FROM master.dbo.spt_values AS SV WHERE SV.[type] = N'P' AND SV.number BETWEEN 1 AND 400; 以及以下设置: SET NOCOUNT ON; SET STATISTICS IO, TIME OFF; SET STATISTICS XML OFF; SET TRANSACTION ISOLATION LEVEL READ COMMITTED; 以下SELECT语句将在6秒钟左右完成(demo,plan): DECLARE @n integer = 400; …

2
“ SELECT TOP”效果问题
我有一个查询,使用select可以运行得更快,top 100而没有则要慢得多top 100。返回的记录数为0。能否解释查询计划中的差异或在解释差异的地方共享链接? 没有top文本的查询: SELECT --TOP 100 * FROM InventTrans JOIN InventDim ON InventDim.DATAAREAID = 'dat' AND InventDim.INVENTDIMID = InventTrans.INVENTDIMID WHERE InventTrans.DATAAREAID = 'dat' AND InventTrans.ITEMID = '027743' AND InventDim.INVENTLOCATIONID = 'КзРЦ Алмат' AND InventDim.ECC_BUSINESSUNITID = 'Казахстан'; 以上查询计划(不含top): https://pastebin.com/cbtJpxFf IO和TIME统计信息(无top): SQL Server parse and compile time: CPU time = 0 …

2
为什么不使用IS NULL值的筛选索引?
假设我们有一个这样的表定义: CREATE TABLE MyTab ( ID INT IDENTITY(1,1) CONSTRAINT PK_MyTab_ID PRIMARY KEY ,GroupByColumn NVARCHAR(10) NOT NULL ,WhereColumn DATETIME NULL ) 和一个过滤的非聚集索引,如下所示: CREATE NONCLUSTERED INDEX IX_MyTab_GroupByColumn ON MyTab (GroupByColumn) WHERE (WhereColumn IS NULL) 为什么此索引未针对此查询“覆盖”: SELECT GroupByColumn ,COUNT(*) FROM MyTab WHERE WhereColumn IS NULL GROUP BY GroupByColumn 我正在得到这个执行计划: KeyLookup用于WhereColumn IS NULL谓词。 这是计划:https …

1
从索引列上非常大的表中选择SELECT TOP 1非常慢,但不是相反的顺序(“ desc”)
我们有一个大型数据库,大约1TB,在功能强大的服务器上运行SQL Server 2014。几年一切正常。大约2周前,我们进行了全面维护,其中包括:安装所有软件更新;重建所有索引和紧凑的数据库文件。但是,我们没想到在实际负载相同的情况下,在某些阶段数据库的CPU使用率会增加100%以上至150%。 经过大量的故障排除后,我们将其范围缩小到一个非常简单的查询,但找不到解决方案。查询非常简单: select top 1 EventID from EventLog with (nolock) order by EventID 它总是需要约1.5秒!但是,带有“ desc”的类似查询始终大约需要0毫秒: select top 1 EventID from EventLog with (nolock) order by EventID desc PTable大约有5亿行;EventID是ASC数据类型为bigint(标识列)的主聚集索引列(有序)。有多个线程在顶部的数据表中插入数据(较大的EventID),有1个线程从底部的数据表中删除数据(较小的EventID)。 在SMSS中,我们验证了两个查询始终使用相同的执行计划: 聚集索引扫描; 估计行数和实际行数均为1; 估计的执行次数和实际的执行次数均为1; 估计I / O成本为8500(似乎很高) 如果连续运行,则两者的查询成本都是相同的50%。 我更新了索引统计信息with fullscan,问题仍然存在;我再次重建了索引,问题似乎消失了半天,但又回来了。 我通过以下方式打开了IO统计信息: set statistics io on 然后连续运行两个查询,发现以下信息: (对于第一个查询,慢速查询) 表“ PTable”。扫描计数1,逻辑读407670,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。 (对于第二个查询,快速查询) …

1
操作员在执行溢出级别2的过程中使用tempdb溢出数据
我正在努力通过警告Operator usedtempdb 将查询计划上的排序操作的成本降至最低to spill data during execution with spill level 2 我发现有几个与泄漏级别为1的执行过程中的泄漏数据有关的帖子,但与级别2无关,而级别1似乎是由于过时的统计信息引起的,级别2呢?我找不到与关联的任何内容level 2。 我发现本文与排序警告有关非常有趣: 永不忽略SQL Server中的排序警告 我的SQL Server? Microsoft SQL Server 2014(SP2)(KB3171021)-12.0.5000.0(X64)2016年6月17日19:14:09版权所有(c)Windows NT 6.3(Build 9600:)上的Microsoft Corporation Enterprise Edition(64位)(系统管理程序) 我的硬件? 运行下面的查询以查找硬件: -来自SQL Server 2012的硬件信息 SELECT cpu_count AS [Logical CPU Count], hyperthread_ratio AS [Hyperthread Ratio], cpu_count/hyperthread_ratio AS [Physical CPU Count], physical_memory_kb/1024 AS …

3
在IF EXISTS中包装查询会使它非常慢
我有以下查询: select databasename from somedb.dbo.bigtable l where databasename ='someval' and source <>'kt' and not exists(select 1 from dbo.smalltable c where c.source=l.source) 上面的查询将在三秒钟内完成。 如果上面的查询返回任何值,我们希望存储过程为EXIT,因此我将其重写如下: If Exists( select databasename from somedb.dbo.bigtable l where databasename ='someval' and source <>'kt' and not exists(select 1 from dbo.smalltable c where c.source=l.source) ) Begin Raiserror('Source missing',16,1) Return …

3
索引对更新列不在索引中的更新语句的影响
我经常看到人们说索引变慢update,delete并且insert。这用作一揽子声明,就好像它是绝对的一样。 在调整数据库以提高性能的同时,我不断遇到这种情况,这种情况似乎在逻辑上对我来说与该规则相矛盾,而且我在任何地方都找不到其他方式可以说或解释的人。 在SQL Server中,并且我相信/假定将使用大多数其他DBMS,您的索引是根据您指定的特定列创建的。插入和删除将始终影响整个行,因此没有办法不会影响索引,但是更新似乎更加独特,它们可以专门影响某些列。 如果我有未包含在任何索引中的列并更新了它们,它们是否会因为我在该表中的其他列上有索引而放慢了速度? 例如,在我的User表中,我有一个或两个索引,主键是Identity / Auto Increment列,外键列上可能还有另一个。 如果我更新没有索引直接在其上的列(例如说他们的电话号码或地址),由于在任何一种情况下我在该表的其他列上都有索引,此更新是否会变慢?我要更新的列不在索引中,因此从逻辑上讲,不应更新索引,不是吗?如果有的话,如果我使用WHERE子句中的索引,我认为它们会加快速度。

1
使用RECOMPILE查询提示时查询之间执行时间的巨大差异
我在同一SQL Server 2005实例上运行两个几乎相同的查询: 第一个是SELECTLINQ生成的原始查询(我知道,我知道...我不是应用程序开发人员,只是DBA :)。 第二个与第一个完全相同,最后添加一个OPTION (RECOMPILE)。 没有其他改变。 第一次运行需要55秒。 第二个需要2秒。 两个结果集是相同的。 为什么这个提示会带来如此惊人的性能提升? 的在线丛书条目RECOMPILE未提供详细的解释: 指示SQL Server数据库引擎在执行后放弃为查询生成的计划,从而迫使查询优化器在下次执行同一查询时重新编译查询计划。在不指定RECOMPILE的情况下,数据库引擎缓存查询计划并重新使用它们。编译查询计划时,RECOMPILE查询提示将使用查询中任何局部变量的当前值;如果查询在存储过程中,则将当前值传递给任何参数。 当只需要重新编译存储过程中的一部分查询而不是整个存储过程时,RECOMPILE是创建使用WITH RECOMPILE子句的存储过程的有用替代方法。有关更多信息,请参见重新编译存储过程。创建计划指南时,RECOMPILE也很有用。有关更多信息,请参见使用计划指南优化已部署应用程序中的查询。 由于我的查询有很多局部变量,因此我猜测当我使用OPTION (RECOMPILE)查询提示时,SQL Server能够(严重)优化它。 我到处看的人都说OPTION (RECOMPILE)应该避免。对此的解释通常是,使用此提示,SQL Server无法重用此执行计划,因此必须浪费时间每次重新编译它。(但是)鉴于巨大的性能优势,我倾向于认为这次使用此查询提示将是一件好事。 我应该使用它吗?如果没有,是否有一种方法可以强制SQL Server在没有此提示且不更改应用程序的情况下使用更好的执行计划?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.