在 sql server 2008 中对百万记录表进行简单但缓慢的查询
Posted
技术标签:
【中文标题】在 sql server 2008 中对百万记录表进行简单但缓慢的查询【英文标题】:Simple but slow query on million records table in sql server 2008 【发布时间】:2012-08-05 14:59:23 【问题描述】:朋友们好,提前感谢您的帮助。
我正在执行一个在两个表之间执行连接的简单查询:
SELECT
F5_CNOMBRE,
F5_CTD,
F5_CNUMSER,
F5_CNUMDOC,
F5_DFECDOC,
F5_NIMPORT,
CD_DFECCAN,
CD_CCODART
FROM ft1
INNER JOIN cc1
ON RTRIM(cc1.CD_CNRODOC) = RTRIM(ft1.F5_CNUMSER) + ft1.F5_CNUMDOC
WHERE F5_CGLOSA LIKE @varNroExpediente + '%'
表 ft1 大约有 100 万条记录,表 cc1 大约有 70 万条记录。
当没有人在/使用这些表时,查询运行速度很快,但是当用户使用它们时,查询大约需要 30/50 秒才能完成。
我正在考虑创建一个索引视图,索引字段 ft1.F5_CNUMSER 和 ft1.F5_CNUMDOC。我认为这会提高性能。我也想听听你对这个问题的看法,如果我在视图上创建索引,查询的表是否有可能在操作中被损坏,这些表对于实际系统来说是非常重要的。
我很欣赏我能在这个主题上获得的洞察力。
【问题讨论】:
CD_CNRODOC
和 F5_CNUMSER
是否有充分的理由在数据库中不被修剪? ft1
上是否有包含 F5_CNUMSER
(已修剪)和 F5_CNUMDOC
的索引? (即一个索引有两列。)索引统计信息是最新的吗?
@HABO 不幸的是,这些修剪是必要的,因为某些数据包含空白。该表没有活动索引,因此在我的理解中没有活动索引统计信息。
您选择的那 8 列是否只选择了这两个表的一小部分列?还是他们几乎占了整个桌子?
@marc_s ft1 表有 90 列,cc1 有 57 列
【参考方案1】:
看到您的两个表总共有 147 列,但您“只”选择了其中的 8 个(一件好事!),通过在您的表上设置两个索引,您可能会获得良好的性能提升:
在表ft1
上,在F5_CGLOSA
(您在WHERE
子句中使用)创建索引并包含该表中的其他列:
CREATE INDEX IX01_ft1
ON dbo.ft1 (F5_CGLOSA)
INCLUDE(F5_CNOMBRE, F5_CTD, F5_CNUMSER, F5_CNUMDOC, F5_DFECDOC, F5_NIMPORT)
在另一张表cc1
上,在两列中较小的列上创建索引(取决于它们的数据类型)并包含另一列 - 我只是“猜测”它可能是这样的:
CREATE INDEX IX01_ft1
ON dbo.cc1(CD_DFECCAN)
INCLUDE(CD_CCODART)
这样,您的查询(它需要的所有列)被这两个索引“覆盖”,并且能够只扫描这两个索引(并结合这些扫描的结果),而不必扫描整个表(更大、更多的列)可以带来显着的改进(希望如此!)。
【讨论】:
谢谢,我可以在视图上创建索引而不是在表上创建索引吗?我没有表修改权限。顺便说一句,Glosa 字段不是唯一字段(是 cmets 字段)。 @CoderRoller:不,您不能在视图上创建索引 - 除非您已将其设为 indexed 视图(在该视图上创建了聚集索引)。另外:F5_CGLOSA
不需要是唯一的 - 它只是被索引,仅此而已【参考方案2】:
当然,用索引视图实现连接可能很有用,因为连接非常讨厌。索引对此无能为力。创建视图时,将 F5_CGLOSA 设为第一个聚集索引列,以便您的查询可以对其进行查找。
不确定这对您来说是否可行,但您能否 a) 更改连接列,这样您就不必加入函数结果并成为 SARGable 并且 b) 找出该查询的并发用户导致阻塞的原因?也许你可以通过打开快照隔离来解决这个问题。
【讨论】:
谢谢,我认为没有办法改变连接,但我也在考虑添加隔离,我会尝试看看它在生产中的表现。如果我为查询添加索引视图,在其上设置的索引可能会损坏表? 除了写入速度稍慢并且某些模式操作不再可能(例如,重命名视图中的列)之外,您不会造成任何伤害。以上是关于在 sql server 2008 中对百万记录表进行简单但缓慢的查询的主要内容,如果未能解决你的问题,请参考以下文章