我正在尝试优化表查找,因为执行计划显示了非常大的并行化表扫描。该表名为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%'));
提前感谢任何建议!
答案 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提到了一些限制:
您无法使用BETWEEN
,NOT IN
,CASE
表达式,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;我感动......