AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 197
Accepted
Andrew Barber
Andrew Barber
Asked: 2011-01-05 10:48:09 +0800 CST2011-01-05 10:48:09 +0800 CST 2011-01-05 10:48:09 +0800 CST

我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 772

我已经有点知道这个问题的答案了,但我总觉得在这个话题上我还需要了解更多。

我的基本理解是,一般而言,仅包含您可能在任何给定时间查询/排序的所有字段的单个索引不太可能有用,但我已经看到了这种类型的东西。比如,有人想,“好吧,如果我们只是把所有这些东西放在一个索引中,数据库就可以用它来找到它需要的东西”,而没有看到一些正在运行的实际查询的执行计划。

想象一下这样的表:

id int pk/uid
name varchar(50)
customerId int (foreign key)
dateCreated datetime

我可能会看到一个包含name,customerId和dateCreated字段的索引。

但我的理解是,这样的索引不会在查询中使用,例如:

SELECT [id], [name], [customerId], [dateCreated]
   FROM Representatives WHERE customerId=1 
   ORDER BY dateCreated

对于这样的查询,在我看来,一个更好的主意是包含customerId和dateCreated字段的索引,customerId字段为“第一”。这将创建一个索引,该索引将以这样的方式组织数据,以便该查询可以快速找到它需要的内容 - 按照它需要的顺序。

我看到的另一件事,也许和第一件事一样频繁,是每个字段上的单独索引。name因此,在customerId和dateCreated字段上各有一个。

与第一个示例不同,这种安排有时在我看来至少部分有用。查询的执行计划可能显示至少它使用 上的索引customerId来选择记录,但它没有使用带有dateCreated字段的索引来对它们进行排序。


我知道这是一个广泛的问题,因为对任何特定表集的任何特定查询的具体答案通常是查看执行计划说明它将做什么,否则将表和查询的细节纳入帐户。另外,我知道这取决于查询可能运行的频率,而不是为其维护特定索引的开销。

但我想我要问的是作为索引的一般“起点”,为特定的、频繁提取的查询和 WHERE 或 ORDER BY 子句中的字段设置特定索引的想法是否有意义?

sql-server index
  • 2 2 个回答
  • 2689 Views

2 个回答

  • Voted
  1. Best Answer
    David Spillett
    2011-01-05T11:23:31+08:002011-01-05T11:23:31+08:00

    您是对的,您的示例查询不会使用该索引。

    如果出现以下情况,查询规划器将考虑使用索引:

    • 查询中引用了其中包含的所有字段
    • 引用了一些从头开始的字段

    它将无法使用以查询未使用的字段开头的索引。

    所以对于你的例子:

    SELECT [id], [name], [customerId], [dateCreated]
       FROM Representatives WHERE customerId=1 
       ORDER BY dateCreated
    

    它将考虑以下索引:

    [customerId]
    [customerId], [dateCreated]
    [customerId], [dateCreated], [name]
    

    但不是:

    [name], [customerId], [dateCreated]
    

    如果它同时发现两者[customerId],那么[customerId], [dateCreated], [name]它是否更喜欢其中一个的决定将取决于索引统计数据,而索引统计数据取决于对字段中数据平衡的估计。如果[customerId], [dateCreated]已定义,则它应该比其他两个更喜欢,除非您给出相反的特定索引提示。

    根据我的经验,为每个字段定义一个索引也很常见,尽管这很少是最佳的,因为在插入/更新时更新索引所需的额外管理以及存储它们所需的额外空间在一半时被浪费了它们可能永远不会被使用 - 但除非您的数据库看到写入繁重的负载,否则即使索引过多,性能也不会很糟糕。

    频繁查询的特定索引通常会因表或索引扫描而变慢,这通常是一个好主意,但不要过度使用,因为您可能会将一个性能问题换成另一个问题。例如,如果您确实定义[customerId], [dateCreated]为索引,请记住查询计划器将能够将其用于将使用索引的查询([customerId]如果存在)。虽然使用 just[customerId]会比使用复合索引稍微更有效,但可以通过最终让两个索引而不是一个竞争 RAM 中的空间来缓解这种情况(尽管如果您的整个正常工作集很容易放入 RAM,那么这种额外的内存竞争可能不会一个问题)。

    • 28
  2. BradC
    2011-01-11T15:40:48+08:002011-01-11T15:40:48+08:00

    要回答您最初的问题,是的,必须围绕查询设计索引,而不仅仅是表。索引中字段的顺序至关重要。设计单个索引以优化多个查询更加困难,您将不得不做出权衡。

    关于您的第二点,是的,单个字段上的一堆索引非常常见。我一直在我的环境中看到它,这对我来说通常是一个危险信号,即开发团队没有与 DBA 合作设计适当的索引。

    我设计索引的策略是索引:

    • WHERE 中使用的字段(按选择性顺序)
    • ORDER BY 中使用的字段
    • 包括其他字段(如有必要)以制作覆盖索引

    所以对于你的例子:

    SELECT [id], [name], [customerId], [dateCreated]
       FROM Representatives WHERE customerId=1 
       ORDER BY dateCreated
    

    我可能会在 (CustomerID, dateCreated) INCLUDE (id, name) 上设计一个索引。这个覆盖索引意味着查询不必访问原始表,从而大大提高了性能。

    不过,这个例子几乎太简单了。仅 (CustomerID) 上的简单索引的性能几乎相同(假设每个客户只有一个代表,因此只需要对表进行一次书签查找)。根据对表运行的其他查询,实际对 (CustomerID, ID)执行聚集索引甚至可能是有益的。

    • 6

相关问题

  • 死锁的主要原因是什么,可以预防吗?

  • 我在索引上放了多少“填充”?

  • 如何确定是否需要或需要索引

  • RDBMS 上的“索引”是什么意思?[关闭]

  • 如何在 MySQL 中创建条件索引?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    您如何显示在 Oracle 数据库上执行的 SQL?

    • 2 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    我可以查看在 SQL Server 数据库上运行的历史查询吗?

    • 6 个回答
  • Marko Smith

    如何在 PostgreSQL 中使用 currval() 来获取最后插入的 id?

    • 10 个回答
  • Marko Smith

    如何在 Mac OS X 上运行 psql?

    • 11 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Marko Smith

    将数组参数传递给存储过程

    • 12 个回答
  • Martin Hope
    Manuel Leduc PostgreSQL 多列唯一约束和 NULL 值 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler 什么时候应该将主键声明为非聚集的? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - 哪个更好作为主键? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick 如何优化大型数据库的 mysqldump? 2011-01-04 13:13:48 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve