使用 SQL Server 时,可以有多个应用程序主机访问它,每个应用程序可以有一个或多个连接。每个连接都可能有多个事务(如果我错了,请纠正我)。每个事务都可以执行查询或非查询 SQL。
根据我的经验,如果我查询一个被独占锁定的表,我很容易遇到超时。如果两个不同的应用程序锁定同一资源,我还看到 SQL Server 检测并抛出死锁异常而不是超时。我还显示了重建索引超时,这可能是由于有人仍然连接到表。
但是,我也遇到了一种死锁,SQL Server 没有检测到它或超时。在这个应用程序中,它打开了两个连接,两个独立的事务,其中第一个事务锁定了一个资源,第二个事务尝试访问相同的资源,但它没有关闭第一个事务。
有人会提供超时和/或死锁类型的列表,这将帮助我在处理应用程序时避免此类情况。
我读到,如果我使用 IsolationLevel.ReadUncommitted,则查询不应发出任何锁。但是,当我对此进行测试时,我看到了以下锁定:
Resource_Type:HOBT
Request_Mode:S(共享)
什么是 HOBT 锁?与 HBT(堆或二叉树锁)相关的东西?
为什么我还会得到 S 锁?
在不打开隔离级别快照选项的情况下进行查询时如何避免共享锁定?
我正在 SQLServer 2008 上对此进行测试,并且快照选项设置为关闭。查询仅执行选择。
我可以看到 Sch-S 是必需的,尽管 SQL Server 似乎没有在我的锁定查询中显示它。为什么它仍然发出共享锁?根据:
在该
READ UNCOMMITTED
级别运行的事务不会发出共享锁,以防止其他事务修改当前事务读取的数据。
所以我有点困惑。
如果用户从不运行REBUILD
或REORGANIZE
在他们的数据库上运行,SQL Server 是否仍然以某种方式对索引进行碎片整理?
MSDN 建议,如果索引超过 30% 的碎片,建议运行REBUILD
而不是REORGANIZE
. REORGANIZE
多次运行会做同样的事情REBUILD
吗?
我对此感到疑惑,因为我有一个具有高度碎片化索引的客户端。他们REORGANIZE
每个周末都运行该索引,随着时间的推移,他们的索引似乎被整理了碎片。
这有意义吗?
我有一个包含超过 1800 万条记录的表。我有一个每天从该表中清除数据的过程。索引碎片很少。
该表具有高事务吞吐量。它每秒存储大约 3 到 5 条新记录,因此我们知道清除该表的旧记录需要很快。
删除语句是这样的:
Delete top 1000
From MyTable
Where CreationDate < 'Some Date'
Run Code Online (Sandbox Code Playgroud)
理想情况下,我们会一直运行它,直到无法删除更多行。
对于前 600 万条记录,删除过程进展顺利,但随着时间的推移,删除开始变慢,直到影响访问同一表的其他应用程序。此外,许多外键索引变得碎片化。
我的问题是:
我使用的是 SQL Server 2005 标准版。
[更新] 我在这里包含了更多信息实际表名称为“VehicleLocation”关键列:
索引
VehicleLocation 的对象依赖关系(约 1050 万行)
以上所有表在其主键和 VehicleLocationKey (FK) 表上都有索引。
此外,我们使用 GUID 作为主键(坏主意,但它是遗留的)。最重要的是,我看到 VehicleLocationTP …
我正在尝试编写一个查询来获取表中状态的持续时间。此查询需要在 SQL Server 2008 中工作。
假设我有下表:
Key Value RecordDate
1 1 2012-01-01
2 1 2012-01-02
3 1 2012-01-03
4 5 2012-01-05
5 5 2012-01-05 12:00:00
6 12 2012-01-06
7 1 2012-01-07
8 1 2012-01-08
Run Code Online (Sandbox Code Playgroud)
我想得到以下结果
Value StartDate EndDate Duration
1 2012-01-01 2012-01-05 4 days
5 2012-01-05 2012-01-06 1 days
12 2012-01-06 2012-01-07 1 days
1 2012-01-07 NULL NULL
Run Code Online (Sandbox Code Playgroud)
基本上我想在它改变之前获取值的持续时间。
我正在接近某个地方,但仍然无法弄清楚:
SELECT [Key], [Value],
MIN(RecordDate) OVER(PARTITION BY [Value]) as 'StarDate',
MAX(RecordDate) OVER(PARTITION BY [Value]) as 'EndDate',
DATEDIFF(day, (MIN(RecordDate) OVER(PARTITION BY [Value])), …
Run Code Online (Sandbox Code Playgroud) 我有一张有 400 万条记录的表。它在日期列(记录创建日期)上有一个聚集索引。它有 5 个表引用这个表,都有 FK 索引。
机器没有停机时间。我有一个程序可以清理超过 31 天的记录。它创建一个连接,删除 TOP 1000 行,关闭连接,然后重复直到所有旧记录都被删除。
删除非常缓慢,每 10 秒删除大约 1000 行。理想情况下,我想每秒执行 1000 行。
我注意到在删除过程中,它对索引执行了大量页面锁定。
我想知道是否有更快的方法来删除数据而不会导致超时。
我的想法是,如果我做一个表锁,执行删除,等待一秒钟,以便它不会超时其他事务,然后再次执行删除,那会更好。我的猜测是,如果我做表锁,应该减少行锁或页锁的数量,这可能会加快删除速度。
我对这个问题的任何建议都会有所帮助。
请注意,硬盘或数据库没有碎片,它是 RAID 10 机器。
[更新] 感谢询问性能执行计划。看起来实时环境与我的开发环境不同。它正在执行索引扫描而不是索引查找。我想我必须更多地调查它为什么会进行索引扫描。
[更新 2] 这是我们对其中一些表的索引。我们的索引命名约定是 [TableName]_[ColumnName],抱歉我们没有使用 MSSQL 命名标准。此外,事实证明,客户端有 96% 的碎片索引(VehicleLocationTP_VehicleLocationKey),这绝对是问题之一。这可能是 SQL2005 使用索引扫描而不是索引查找的原因。
[更新 3] 我终于能够在他们的测试服务器上测试删除查询,而不是在我自己的电脑上。他们在我的机器上运行 SQL 2005 Standard 和 SQL 2008 R2 Express。大约 95% 的索引碎片化,重建索引将删除从 25-50% 提高。当他们的 SQL Server 不断运行时,很难进行性能测试。但是,查看实际执行计划,它与估计的相同。所以你是对的,碎片不会影响执行计划。我的猜测是它可能是表中的行数。也许如果表很小,它会使用索引扫描,而不是索引查找。
此外,这篇文章让我更深入地了解为什么它是索引扫描Index Scan vs Index Seek
当执行计划显示索引扫描时,它真正扫描了整个表。它称之为索引扫描,因为 VehicleLocationAPC 是一个簇索引表。这消除了一些混乱。这意味着没有使用索引,它正在执行整个表扫描。
另一个需要意识到的是VehicleLocationAPC中数据的内容。VehicleLocationKey 几乎一直都是唯一的。我们的应用程序为每个 VehicileLocation 行生成一个 VehicleLocationAPC 行。我的猜测是,正因为如此,SQL Server …