【问题标题】:SQL Server - index on a computed column?SQL Server - 计算列上的索引?
【发布时间】:2010-11-22 07:59:59
【问题描述】:

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

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

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

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

00000012345MoreStuff
00000012345Whatever
19834212345
Houses12345837443GGD
00000023456MoreStuff

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

【问题讨论】:

  • 要使JOIN 使用索引,您应该转换列,使其以您正在搜索的条件开头。至于现在,你的算法太模糊了。 “前导零并不总是前导零”很难向 SQL Server 解释。 FULLTEXT 索引可用于搜索单词中的前缀(而不是整列),但您仍然应该将数据拆分为单词。您能否更清楚地定义您的搜索算法?
  • 如果您正在寻找索引SEEK,那么您还需要知道您的数据是否具有足够的选择性。也就是说,数据库中的总值与不同值的数量之比是多少。 “交叉点”实际上非常低(取决于桌子的宽度)。此外,如果您的索引不包括您从中选择的列,那么您从书签查找中执行的读取次数将使 SQL Server 忽略您的全新索引。您能否提供选择性/选择列表的详细信息?

标签: sql-server sql-server-2008 indexing calculated-columns


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      在您的表中添加一个计算列,并在该列上创建索引。

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

      然后在上面创建一个索引。

      CREATE INDEX CodeHeadIdx ON MyTable.CodeHead
      

      【讨论】:

        【解决方案4】:

        假设您的字段采用这种格式:

        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'
        

        【讨论】:

        • 这就是我最终的结果。我只是对视图进行模式绑定,然后我就可以开始了。谢谢指点。
        猜你喜欢
        • 2017-08-07
        • 2010-09-29
        • 2010-11-01
        • 1970-01-01
        • 2018-05-12
        • 1970-01-01
        • 2011-05-04
        • 1970-01-01
        相关资源
        最近更新 更多