更新语句执行时间太长

时间:2011-09-02 15:25:29

标签: sql sql-server indexing cardinality

我正在运行一个简单的更新语句。执行时间太长。以下是更新和索引详细信息。

Exported列的默认值为0

UPDATE PAR_ITM SET exported = -1 WHERE exported < 1

索引:

CREATE NONCLUSTERED INDEX [IX_PAR_ITM_Exported_1]
ON [dbo].[PAR_ITM] ([exported] ASC)
WITH (
  PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = ON, SORT_IN_TEMPDB = OFF,
  IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON,
  ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 80
) ON [PRIMARY]

5 个答案:

答案 0 :(得分:3)

因此,您将导出设置为-1,其中导出已经等于-1。也许将您的are子句更改为WHERE exported = 0会更少的行?

答案 1 :(得分:3)

基数低
您正遇到一个名为low cardinality的问题 见wikipedia

问题
简而言之,每个数据库(我知道)都会拒绝在低基数列上使用索引。

还有更多
良好 数据库如果猜测选择 (选择的低基数)将会击中很多行,也会拒绝使用索引< / strong> ,即使列本身有很多不同的值 (列的高基数)

为什么 - 在这里插入数据库 - 不使用索引?
这是问题所在 如果数据库中所有行的超过50%(每个数据库不同)具有相同的值,则DB将不使用索引,因为使用索引是没有意义的。

对于大多数行执行2次读取是没有意义的(如果您可以执行一次读取(在表格本身上),则对索引读取1,对表格读取2)。 无论如何,数据库必须读取大多数行,所以它只是继续读取它们 数据库必须使用其最慢的访问机制(全表扫描)后退这一事实导致您的速度变慢。

解决方案
增加列的基数或增加选择的基数 在其他工作中,请确保选择少于50%的所有行,并确保SQL服务器知道(或可以猜测)这一点。

数据库如何知道列的基数?
一个好的DB在执行选择/更新/插入时保持表和列的统计信息。通过这种方式,它具有做出明智决策所需的信息。

强制使用索引会加快查询速度吗?
不,它会减慢速度。

SO链接
MySQL: low cardinality/selectivity columns = how to index?
Indexing & alternatives for low-selectivity columns

答案 2 :(得分:1)

可能有助于了解其中包含的记录数量:

Select Count(*)
FROM PAR_ITM 
WHERE exported < 1

基本上要更新多少行。当然,即使一百万行也会相对较快地完成。

其他类型的查询是否在您的服务器上执行缓慢?

答案 3 :(得分:1)

我认为你不应该在这里使用非聚集索引,因为它似乎根本没有exported的唯一性。非聚集索引的经验法则是95%唯一性,因为查询优化器可能不会使用索引,这意味着您无缘无故地放慢速度。

请查看本文以获取有关非聚集索引的说明:

http://www.sql-server-performance.com/2007/nonclustered-indexes/

答案 4 :(得分:1)

您还可能涉及另一个查询的阻止情况。