4

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

导出列的默认值为 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]
4

5 回答 5

3

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

于 2011-09-02T15:32:20.067 回答
3

基数低
您正在为一个名为low cardinality.
参见维基百科

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

还有更多
如果一个好的数据库猜测许多行将被选择命中(选择的低基数),即使列本身有很多不同的值(列的高基数),它也会拒绝使用索引

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

如果您可以进行一次读取(在表本身上),则对大多数行进行 2 次读取(索引读取 1,表读取 2)是没有意义的。
无论如何,数据库必须读取大多数行,因此它会继续读取它们。
数据库必须使用其最慢的访问机制(全表扫描)这一事实是导致您运行缓慢的原因。

解决办法
增加column的cardinality或者增加select的cardinality。
在其他作品中,请确保您选择的行少于 50%,并确保 SQL 服务器知道(或可以猜到)这一点。

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

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

SO链接
MySQL:低基数/选择性列=如何索引?
低选择性色谱柱的索引和替代品

于 2011-09-02T15:38:37.120 回答
1

了解其中包含多少条记录可能会有所帮助:

Select Count(*)
FROM PAR_ITM 
WHERE exported < 1

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

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

于 2011-09-02T15:32:04.817 回答
1

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

看看这篇文章关于非聚集索引的解释:

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

于 2011-09-02T15:35:27.113 回答
1

您还可能因另一个查询而陷入阻塞情况。

于 2011-09-02T15:37:55.787 回答