是否可以编写一个过滤索引,其中列值不相似' X&#39 ;?

时间:2014-09-18 21:06:27

标签: sql-server sql-server-2012 query-optimization filtered-index

我正在尝试优化表查找,因为执行计划显示了非常大的并行化表扫描。该表名为Opportunity,我正在过滤的列为Name。具体来说,我希望所有没有“Supplement”的行作为Name

的一部分
WHERE ([Name] NOT LIKE '%Supplement%');

我一直在寻找一种优化方法,并且遇到过滤索引,这是我需要的,但它们似乎不喜欢LIKE关键字。是否有另一种方法来创建像这样的过滤索引?

该表有〜53k行,直接查询服务器时需要4秒才能获取数据,但当我将其作为链接服务器查询时(这就是我需要的),需要2分钟。为了改善这段时间,我将查询移出了与链接服务器通信的脚本,并在远程服务器上创建了一个视图。仍需要永远。

这是我到目前为止所尝试的内容,但是SSMS说这是无效的:

CREATE NONCLUSTERED INDEX [FX_NotSupplementOpportunities]
    ON      [Opportunity]([Name])
    WHERE   (([Name] NOT LIKE '%Supplement%')
            AND ([Name] NOT LIKE '%Suplement%')
            AND ([Name] NOT LIKE '%Supplament%')
            AND ([Name] NOT LIKE '%Suppliment%'));

提前感谢任何建议!

3 个答案:

答案 0 :(得分:3)

您可以使用Indexes on Computed Columns 一个例子是:

CREATE TABLE [dbo].[MyTab](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Text] [varchar](max) NULL,
    [OK]  AS (case when NOT [text] like '%abc%' then (1) else (0) end) PERSISTED NOT NULL,
 CONSTRAINT [PK_MyTab] 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]

GO
CREATE NONCLUSTERED INDEX [idx_OK] ON [dbo].[MyTab] 
(
    [OK] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

答案 1 :(得分:2)

不幸的是,在过滤索引的条件下,你可以放置许多限制。

我在MSDN中找不到任何具体内容,但Brent Ozar撰写的这篇博文:What You Can (and Can’t) Do With Filtered Indexes提到了一些限制:

您无法使用BETWEENNOT INCASE表达式,OR

他们没有提及LIKE,但简单的测试(正如你所做的那样)证实你也不能。您甚至无法使用可以重写为允许的(NOT (a >= 7))的{​​{1}}。

一种想法是在持久化列上使用case表达式,然后使用过滤索引中的持久列 - 但这是过滤索引的另一个限制!

那么,你做什么?我们唯一想到的是创建一个持久化列并在简单(未过滤)的索引中使用它。类似的东西:

(a < 7)

然后使用以下列添加索引:

ALTER TABLE  dbo.Opportunity
    ADD special_condition AS (CASE WHEN [Name] NOT LIKE '%Supplement%' 
                                  THEN 1 ELSE 0 END) 
        PERSISTED;

并在查询中使用CREATE NONCLUSTERED INDEX FX_NotSupplementOpportunities ON dbo.Opportunity (special_condition, [Name]) ;

答案 2 :(得分:0)

我选择了@ bummi的答案,因为它最接近我的尝试,但它并不是我最终使用的。一点点解释......

因此,经过几个小时的努力来弄清楚如何使查询查找更快,我实际上从一堆并行化的块到两个索引搜索得到它。我对此非常欣喜若狂,但最后我不得不废弃它。问题是远程数据库实际上是我们Salesforce数据的备份。我不得不在同步前后进行一些非常复杂的表和列更改,这些更改只是没有正常工作,并且每次同步都会被删除(每10分钟一次)。

在完成所有这些工作的同时,它最终打击了我,我正在导入数据,然后在我的结尾再次进行格式化。我决定更新远程服务器上的视图,并尽可能地格式化数据,然后导入它。所以,我花了几个小时重写了双方的SQL,并设法将〜25分钟的脚本缩减到~3分钟,这让我非常高兴和满意。

最后,尽管远程服务器上的查询查找未被优化,但它们仍然非常快,主要是因为在大多数表格中平均不超过约5万行I&# 39;我感动......