17

我要加入一个表几十次,每次,我都会根据其中一列的 SUBSTRING 的结果加入(或过滤)(它是一个字符串,但用零填充,我没有不关心最后四位数字)。结果,即使该列已编入索引并且我的查询将使用该索引,它也会进行表扫描,因为 SUBSTRING 本身没有编入索引,因此 SQL Server 必须在加入之前为每一行计算它。

我正在寻找有关如何加快此过程的任何想法。目前,表上有一个视图(它是“SELECT * FROM”,只是为了给表一个友好的名称),我正在考虑在计算的视图中添加一个列,然后对其进行索引。不过,我愿意接受其他建议 - 有什么想法吗?

更多细节: 我应该一开始就分享这个。该表从我们的计费系统接收复制,因此编辑基础表以添加计算列不是一种选择。任何计算列都必须添加到表的视图中。此外,前导零并不总是前导零 - 它们有时是我不感兴趣的其他数据。我想真正的问题是“如何在 VARCHAR 列中间加入数据同时也使用索引的?全文检索?

澄清我的例子 我正在简化,但本质上,假设我正在尝试在具有以下值的列中查找值:

00000012345MoreStuff
00000012345Whatever
19834212345
Houses12345837443GGD
00000023456MoreStuff

我对 SUBSTRING(7,5)="12345" 的行感兴趣,所以我想要第 1-4 行,而不是第 5 行。我建议在我的“SELECT *”视图中添加一列里面有这个子字符串,然后基于它进行索引。这更有意义吗?

4

4 回答 4

13

假设您有这种格式的字段:

00Data0007
000000Data0011
0000Data0015

,您可以执行以下操作:

  • 创建一个计算列:ndata AS RIGHT(REVERSE(data), LEN(data) - 4)

    这会将您的列转换为以下内容:

    ataD00
    ataD000000
    ataD0000
    
  • 在该列上创建索引

  • 发出此查询以搜索字符串Data

    SELECT  *
    FROM    mytable
    WHERE   ndata LIKE N'ataD%'
            AND SUBSTRING(ndata, LEN(N'ataD') + 1, LEN(ndata)) = REPLICATE('0', LEN(ndata) - LEN('ataD'))
    

    第一个条件将使用索引进行粗略过滤。

    第二个将确保所有前导字符(成为计算列中的尾随字符)都是零。

有关性能详细信息,请参阅我的博客中的此条目:

更新

如果您只想在SUBSTRING不更改架构的情况下创建索引,则可以选择创建视图。

CREATE VIEW v_substring75
WITH SCHEMABINDING
AS
SELECT  s.id, s.data, SUBSTRING(data, 7, 5) AS substring75
FROM    mytable

CREATE UNIQUE CLUSTERED INDEX UX_substring75_substring_id ON (substring75, id)

SELECT  id, data
FROM    v_substring75
WHERE   substring75 = '12345'
于 2009-08-24T16:46:59.733 回答
6

计算列添加到表中并在此列上创建索引。

ALTER TABLE MyTable
Add Column CodeHead As LEFT(Code,Len(Code)-4)

然后在此创建一个索引。

CREATE INDEX CodeHeadIdx ON MyTable.CodeHead
于 2009-08-24T16:46:14.040 回答
1

你能用 LIKE 'something%' 语句重新表述你的过滤条件吗?(这适用于索引)

于 2009-08-24T16:02:30.413 回答
0

将列更改为两列 - 您加入的数据和额外的 4 个字符。如您所见,使用列的一部分会减慢速度

于 2009-08-24T16:43:37.773 回答