【问题标题】:which sql query is the best哪个sql查询最好
【发布时间】:2019-04-10 13:51:48
【问题描述】:

我需要在我的应用程序中使用“搜索”功能,在 SQL Server 中执行此操作的最佳方法是什么?

  1. 使用 OR 语句创建包含 1 个包含所有列的大型 where 子句的查询,并创建 1 个包含所有列的索引
SELECT *
FROM Customer
WHERE CustomerNumber LIKE '%' + @SearchValue +'%'
OR LastName LIKE '%' + @SearchValue +'%'
OR FirstName LIKE '%' + @SearchValue +'%'
OR
  1. 使用 UNION 为每列创建单独的查询并为每列创建索引
SELECT * 
FROM Customer 
WHERE CustomerNumber LIKE '%' + @SearchValue +'%'
UNION 
SELECT * 
FROM Customer
WHERE LastName LIKE '%' + @SearchValue +'%'
UNION
SELECT * 
FROM Customer
WHERE FirstName LIKE '%' + @SearchValue +'%'

我听说索引不支持 OR 语句?那么解决方案 2 是唯一正确的解决方案吗?

对于你们中的一些人来说,这似乎是一个非常简单的问题,但我试图理解“为什么”我需要这样做,因此欢迎提供任何背景信息。

【问题讨论】:

  • 它们可能/可能不会返回相同的结果,具体取决于表数据。 (UNION 删除了重复项。)
  • 你从哪里读到索引不支持OR
  • 如果您有两个有效的查询并且您想知道哪个是最好的,测试通常是了解这一点的好方法。支持或不支持 OR 的索引(数据库确实支持它)与这个问题无关,因为您的搜索词无论如何都不能被正常索引搜索(全文索引在这里会很好),因为它们由于通配符而不可搜索。阅读并了解原因很重要。

标签: sql sql-server tsql indexing


【解决方案1】:

两者都不是最佳的,但第一个更好一些。它只扫描一次数据,并且like 的评估被短路以匹配第一个或第二个条件。此外,union 会产生删除重复项的开销。

如果您真的想要性能,请研究数据库提供的全文索引选项。

【讨论】:

  • 谢谢大家的回答,我调查了全文搜索,但似乎没有与 Like '%xxx%' 等价的东西。 (如果我错了,请纠正我)
【解决方案2】:

OR 条件不能优化的任何 rdb 一般都不成立;大多数 RDB 都实现了 AFAIK 跳过索引,这意味着可以优化多范围条件。但是,在您的情况下,由于您的 LIKE 条件以 % 开头,因此不是前缀匹配,因此它们不能通过索引进行优化,因为它们不是范围条件。即便如此,您应该使用OR 组合:它更易于阅读,符合查询的意图,并且UNION 查询很可能会执行多个表扫描,每个子查询一个,而 OR 查询可能会进行一次扫描,这应该会更快。我说“可能”是因为使用理想的查询优化器,所有等效查询都应该被解析为最佳执行计划——在这种情况下,是一次扫描。但优化器远非“理想”。因此,当使用不同 rdb 的 YMMV 时,请使用 OR 查询。

但是,对于这样的查询,如果您正在搜索单词,则应考虑使用全文索引(如果可用),并且它们在大多数 rdbs 中都可用,但查询语法不同。 https://www.mssqltips.com/sqlservertutorial/9136/sql-server-full-text-indexes/

【讨论】:

  • 是的,我在 DB2 中看到了 ORIDX 操作。 +1
【解决方案3】:

这两个查询都不是最佳性能。

对于选项 1 - or 正在扫描许多可能性,这不是更好的方法..您实际上应该使用字符串索引将所有选项组合在一起。

选项 2 - 这比第一个选项慢,因为它正在执行多个选择选项。

【讨论】:

    【解决方案4】:

    不用担心索引。

    这些查询都不会使用任何索引。由于搜索模式以 % 开头,因此他们无论如何都会执行全表扫描。

    第一个将执行一次全表扫描,而第二个将执行三个。因此第一个会更快。

    另外,请记住,第二个查询将返回略有不同的结果集,因为它删除了重复项。

    【讨论】:

    • 查询仍然可以使用索引scan,但不能使用seek。与表扫描相比,这可以显着减少物理 I/O,具体取决于行的大小与正在搜索的列的大小以及匹配行的数量。
    • @HABO 选定的列列表是*,因此使用覆盖索引没有用处。索引范围扫描也没有用,因为没有开始或停止条件。无论如何它都需要扫描所有行。
    猜你喜欢
    • 1970-01-01
    • 2011-12-02
    • 1970-01-01
    • 2022-01-20
    • 2011-12-16
    • 2010-10-22
    • 1970-01-01
    • 2013-05-16
    • 1970-01-01
    相关资源
    最近更新 更多