【问题标题】:How to create non-clustered index for OR Operation如何为 OR 操作创建非聚集索引
【发布时间】:2021-09-23 00:46:37
【问题描述】:

要求:表Product 有名称和条形码

我想创建一个非聚集索引以使用名称或条形码进行搜索

查询样本

DECLARE @Filter NVARCHAR(100) = NULL

SET @Filter = '%' + ISNULL(@Filter, '') + '%'

SELECT *
FROM Product
WHERE Name LIKE @Filter
OR Barcode LIKE @Filter

请帮助我提供独立于名称和条形码的两个索引的任何解决方案 或使用一个索引包括名称和条形码

【问题讨论】:

  • 当您的过滤器可以以 % 开头时,索引将无济于事
  • 创建一个 FULLTEXT 索引并使用 CONTAINS() ?
  • 好吧,当我说它对你没有帮助时,那并不完全正确。 SQL Server 仍然需要搜索每一行,但使用索引会从磁盘读取更少的数据,即仅索引列而不是整行 - 这确实会提高性能。
  • 按名称搜索和按条形码搜索在逻辑上是截然不同的搜索技术。如果您需要使用相同的值搜索两列,则某些内容似乎很糟糕。我建议您重新考虑建议将此查询作为适当路径的决策和实施选择。阅读此kitchen-sink example 以获取有关优化搜索的更多建议 - 特别是动态 sql 建议。

标签: sql-server where-clause non-clustered-index or-operator


【解决方案1】:

这里有几个问题。首先,即使NameBarcode 上存在索引,您的过滤器表达式也无法从索引中受益(在传统意义上用于添加索引),因为该表达式不可搜索。 Brent Ozar 有一篇很棒的文章解释了Why %string% Is Slow

其次,您不能创建单个索引来覆盖两个单独列上的过滤器,其中每列上的过滤器是独立的。这意味着您要么使用两个单独的过滤器(例如:您的 OP),要么您的查询仅包含 Name = 'NameValue' 的过滤器,反之亦然。具有 where 子句的查询:

WHERE 
    Name = 'NameValue' 
    OR 
    Barcode = 'BarcodeValue'

如果存在单独的索引,其中 Name 是第一个列出的列,Barcode 是第一个列出的列,则只能为两个过滤器表达式查找索引。

包含两列的索引主要用于将两列用作过滤器表达式的一部分的过滤器。例如:Name = 'NameValue' AND Barcode = 'BarcodeValue'。考虑索引中每一列的顺序位置也很重要。例如,假设您创建了这个索引: CREATE NONCLUSTERED INDEX NCIX_Product_Name_Barcode ON Product (Name,Barcode); 带有过滤表达式Name = 'NameValue' 的查询仍然可以查找此索引,因为Name 是索引中的第一列,但带有过滤表达式Barcode = 'BarcodeValue' 的查询不能。

在对索引设计做出任何长期决策之前,您应首先熟悉 Microsoft 在 General Index Design Guidelines 中发布的指南。

最后,如果您确实需要在NameBarcode 中搜索字符串匹配项,您应该查看Microsoft 关于full text indexes 的文档,这可能是您以这种方式进行索引搜索的最佳解决方案。

【讨论】:

    猜你喜欢
    • 2021-01-14
    • 2013-01-24
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-05
    相关资源
    最近更新 更多