SQL Server 2005中的XML数据类型
更新:这个问题是音符相关的XML,我重复使用一个nvarchar(MAX),而不是和仍然相同的问题表。我将重新发布一个新话题。SQL Server 2005中的XML数据类型
我有一个表约一百万条记录,该表具有XML领域。查询运行速度非常慢,即使只选择一个ID。有什么我可以做的,以提高这个速度,我已经尝试设置文本行,但SQL服务器不会允许我,我收到错误“无法切换到表中的行文本”。
我希望在修复或知识的任何帮助,我似乎丢失。
感谢
表
/****** Object: Table [dbo].[Audit] Script Date: 08/14/2009 09:49:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Audit](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ParoleeID] [int] NOT NULL,
[Page] [int] NOT NULL,
[ObjectID] [int] NOT NULL,
[Data] [xml] NOT NULL,
[Created] [datetime] NULL,
CONSTRAINT [PK_Audit] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
QUERY
DECLARE @ID int
SET @ID = NULL
DECLARE @ParoleeID int
SET @ParoleeID = 158
DECLARE @Page int
SET @Page = 2
DECLARE @ObjectID int
SET @ObjectID = 93
DECLARE @Created datetime
SET @Created = NULL
SET NOCOUNT ON;
Select TOP 1 [Audit].* from [Audit]
where
(@ID IS NULL OR Audit.ID = @ID) AND
(@ParoleeID IS NULL OR Audit.ParoleeID = @ParoleeID) AND
(@Page IS NULL OR Audit.Page = @Page) AND
(@ObjectID IS NULL OR Audit.ObjectID = @ObjectID) AND
(@Created is null or(Audit.Created > @Created and Audit.Created < DATEADD (d, 1, @Created)) )
您需要在该列上创建主XML索引。高于其他任何事情将有助于您所有的疑问。
一旦你有了这个,你可以在xml数据的XML列中创建索引。
从经验看不过,如果你可以存储在关系表的一些信息,SQL是在搜索比XML更好和索引这一点。即任何关键列和通常搜索的数据都应在可能的情况下进行关联存储。
像你运行查询,表结构,XML内容等肯定会帮助一些信息。很多...
没有任何信息,我会猜测。选择仅ID时,查询运行缓慢,因为您没有ID中的索引。
更新
至少有一些严重的问题,您的查询。
- 除非提供一个ID,所述表只能被扫描的端至端,因为没有索引
- 即使设置一个ID,条件(@ID是NULL OR ID = @ID )不保证是SARGable,因此它可能仍然会导致表扫描。
- 最重要的是:该查询将产生第一套它看到参数的优化“的计划。它将在任何参数组合上重复使用此计划,而不管其是否为NULL。如果存在可供选择的访问路径上的一些变化(即,索引),那么这将会产生影响,但是现在,如果存在@id,查询只能选择使用扫描还是查找。由于构造方式的原因,它总是选择一个扫描,因为OR。
使用此表格设计您的查询今天会运行缓慢,明天变慢,下周不可能随着尺寸的增加而变慢。您必须回头看看您的要求,确定哪些字段需要查询,索引它们并为它们提供单独的查询。将所有可能的过滤器组合在一起不会起作用。
你试图检索XML具有绝对无关的性能问题。你只是粗暴地强制进行表扫描,并希望SQL能够神奇地找到你想要的记录。
所以,如果你想要检索特定ParoleeID,页面和对象ID,你索引你搜索上跑一跑一个查询的领域,只有那些:
CREATE INDEX idx_Audit_ParoleeID ON Audit(ParoleeID);
CREATE INDEX idx_Audit_Page ON Audit(Page);
CREATE INDEX idx_Audit_ObjectID ON Audit(ObjectID);
GO
DECLARE @ParoleeID int
SET @ParoleeID = 158
DECLARE @Page int
SET @Page = 2
DECLARE @ObjectID int
SET @ObjectID = 93
SET NOCOUNT ON;
Select TOP 1 [Audit].* from [Audit]
where Audit.ParoleeID = @ParoleeID
AND Audit.Page = @Page
AND Audit.ObjectID = @ObjectID;
我在我的文章中添加了一些表格/查询信息。查询选择*,但即使只选择ID也需要很长时间。这个特定的查询返回44条记录,运行时间接近一分钟。我做了一些测试,当我有大约700K行时,查询开始停滞,在此之前它跑得很快。 – 2009-08-14 16:57:01
最重要的是:查询将为它看到的第一组参数生成一个“优化的”计划。它将在任何参数组合上重复使用此计划,而不管其是否为NULL。 ---这种说法是错误的。除非你明确提供了一个提示,否则SQL将优化ANY值,如果你知道你有比服务器更好的计划。大多数情况下,由于没有良好的统计信息而导致SQL优化您的数据计划。 – Spence 2010-03-11 12:31:15
请参阅OPTIMIZE FOR(@variable_name {UNKNOWN | = literal_constant} [,... n])http://msdn.microsoft.com/en-us/library/ms181714.aspx – Spence 2010-03-11 12:32:27
SQL Server 2005中 - 十二个技巧对于由托尼·赖特优化查询性能
- 打开执行计划和统计
- 使用聚集索引
- 使用索引视图 个
- 利用了覆盖索引
- 让您的聚集索引小。
- 避免光标
- 归档旧数据
- 分区中的数据正确
- 删除用户定义的内联标量函数
- 用途适用
- 使用计算列
- 使用正确的事务隔离级别
http://tonesdotnetblog.wordpress.com/2008/05/26/twelve-tips-for-optimising-sql-server-2005-queries/
我有相同的情况 - 我们的解决方案是计算列。
对于您需要从XML中频繁获取的那些信息位,我们在“托管”表上创建了一个计算列,该列基本上伸入XML中,并使用XPath从XML中提取必要的值。在大多数情况下,我们甚至可以坚持这个计算列,以便它成为表的一部分,并且可以查询甚至索引,并且查询速度不再是问题(在这些列上)。
我们也尝试在开始XML索引,但是它们的缺点是,他们是在磁盘上绝对是巨大的事实 - 这可能会或可能不会是一个问题。由于我们需要频繁地运送整个数据库(作为SQL备份),所以我们最终放弃了它们。
好的,要设置一个计算列以从您的XML中的信息位中检索,首先需要创建一个存储函数,它将XML作为参数,提取您需要的任何信息,然后传回 - 是这样的:
CREATE FUNCTION dbo.GetShopOrderID(@ShopOrder XML)
RETURNS VARCHAR(100)
AS BEGIN
DECLARE @ShopOrderID VARCHAR(100)
SELECT
@ShopOrderID = @ShopOrder.value('(ActivateOrderRequest/ActivateOrder/OrderHead/OrderNumber)[1]', 'varchar(100)')
RETURN @ShopOrderID
END
然后,你需要计算列添加到您的表,并将其连接到该存储功能:
ALTER TABLE dbo.YourTable
ADD ShopOrderID AS dbo.GetShipOrderID(ShopOrderXML) PERSISTED
现在,您可以轻松地从表中选择数据使用这个新的专栏,就好像它是一个正常的专栏N:
SELECT (fields) FROM dbo.YourTable
WHERE ShopOrderID LIKE 'OSA%'
最重要的是 - 当你更新你的XML,所有的计算列被更新,以及 - 他们总是同步的,没有触发器或其他黑魔法需要!
Marc
这是一个很好的回复,但它不符合我的需求,因为我不想查询某个特定的XML数据,只需选择。你可以看到我上面的查询,我刚刚添加了谢谢。 – 2009-08-14 16:58:08
+1。不知道关于Persisted关键字:)这实际上是快速查询XML的一种非常简洁的方式。 – Spence 2010-03-11 12:27:36
很长一段时间,但这是答案。索引在不到一秒的时间内完成查询! – 2010-03-10 08:30:38