代码之家  ›  专栏  ›  技术社区  ›  schooner

SQL Server索引-类似查询有什么改进吗?

  •  22
  • schooner  · 技术社区  · 15 年前

    我们有一个查询运行在一个相当大的表上,不幸的是,需要在几个varchar字段上使用类似于“%abc%”,以便用户可以搜索部分名称等。SQL Server 2005

    当使用like时,在这些varchar字段上添加索引对选择查询性能有帮助吗?或者它基本上忽略了索引,在这些情况下进行完全扫描?

    在使用like时,还有其他可以提高性能的方法吗?

    5 回复  |  直到 10 年前
        1
  •  20
  •   Lasse V. Karlsen    15 年前

    只有当您向这些列中添加全文搜索,并使用SQL Server的全文查询功能时。

    否则,不,索引将不会有帮助。

        2
  •  12
  •   ahains    15 年前

    通过添加索引,您可能会看到性能改进,这很大程度上取决于具体情况:)

    您的谓词列占行的总大小的多少?您希望匹配多少行?是否需要返回所有与谓词匹配的行,或者只返回前1行或前N行?

    如果搜索具有高选择性/唯一性的值(返回的行太少),并且谓词列只是整个行大小的一小部分,那么索引可能非常有用。它仍将是一个扫描,但您的索引每页所容纳的行数将超过源表所能容纳的行数。

    下面是一个示例,其中总行大小远远大于要搜索的列大小:

    create table t1 (v1 varchar(100), b1 varbinary(8000))
    go
    --add 10k rows of filler
    insert t1 values ('abc123def', cast(replicate('a', 8000) as varbinary(8000)))
    go 10000
    --add 1 row to find
    insert t1 values ('abc456def', cast(replicate('a', 8000) as varbinary(8000)))
    go
    
    set statistics io on 
    go
    select * from t1 where v1 like '%456%'
    --shows 10001 logical reads
    
    --create index that only contains the column(s) to search across
    create index t1i1 on t1(v1)
    go
    select * from t1 where v1 like '%456%'
    --or can force to 
    --shows 37 logical reads
    

    如果您查看实际的执行计划,您可以看到引擎扫描了索引,并在匹配的行上进行了书签查找。或者,如果优化器没有决定自己使用这个计划,您可以直接告诉优化器使用索引: 从T1中选择*(索引(t1i1)),其中v1类似于“%456%”

    如果您只有一小部分具有高度选择性的列可供搜索,那么可以创建多个索引并使用缩减方法。例如,首先从高度选择性索引中确定一组ID(或无论您的pk是什么),然后用一个过滤器对较小的pk集搜索较少选择性的列。

    如果总是需要返回一组大的行,那么使用表扫描几乎肯定会更好。

    因此,可能的优化很大程度上取决于表定义的细节和数据的选择性。

    嗯! -阿德里安

        3
  •  8
  •   marc_s    15 年前

    唯一可以提高性能的方法(除了使用全文索引)是使用“like abc%”—不要在搜索词的两端添加通配符—在这种情况下,索引可以工作。

    如果你的要求是这样的,你必须在你的搜索词的两端都有通配符,你就走运了…

    马克

        4
  •  2
  •   Cruachan    15 年前

    像“%abc%”一样,将始终执行完整的表扫描。这是不可能的。

    你有两种选择。首先是全文搜索,它是为这类问题而设计的,所以我先来看一下。

    或者,在某些情况下,将数据非规范化并将目标字段预处理为适当的标记,然后将这些可能的搜索词添加到单独的一对多搜索表中可能是合适的。例如,如果我的数据总是由一个包含模式“a a a/bbb/ccc”的字段组成,并且我的用户在bbb上搜索,那么我会在插入/更新时将其标记出来(并在删除时删除)。这也是使用触发器而不是应用程序代码的情况之一 许多的 优先考虑。

    我必须强调的是,这不是一种真正的最佳技术,只有当数据与该方法匹配良好,并且出于某种原因,您不想使用全文搜索时才应使用它(类似扫描的数据库性能确实是不可接受的)。它也可能会在生产线的另一端产生维护性头痛。

        5
  •  -3
  •   Mladen Prajdic    15 年前

    在该列上创建统计信息。SQLSRever2005已经优化了字符串内搜索,因此您可能无法适应这种情况。