如果我创建索引,SQL 查询会快得多
Posted
技术标签:
【中文标题】如果我创建索引,SQL 查询会快得多【英文标题】:SQL query is much faster if I create indexes 【发布时间】:2011-12-09 22:54:12 【问题描述】:如果我在一个有 13 列的表中创建 8 个索引可以吗?
如果我从中选择数据并按键对结果进行排序,则查询速度非常快,但如果排序字段不是键,则速度会慢得多。慢了 40 倍。
我基本上要问的是数据库中有很多键是否有任何副作用...
【问题讨论】:
您添加的键越多,在该表中插入/更新记录所需的时间就越长。 小吹牛:这个术语key通常意味着一列具有唯一值,这与索引不同。您可以在非键列上建立索引。 【参考方案1】:在表上创建索引会稍微减慢所有对它的写入操作,但会加快对相关列的读取操作很多。如果您的应用程序不会对该表进行大量写入(大多数应用程序都是如此),那么您会没事的。
【讨论】:
所以它根本不会减慢读取操作的速度吗?只是写作? @JohnSmith:是的,只是写作。如果您请求的读取只涉及 8 个索引中的 1 个,则查询计划器将简单地忽略其他 7 个。 写入会随着行数的增加而逐渐变慢吗? 毫无疑问,但我希望惩罚会随着行数的增加呈次线性增长。无论如何,如果你有一个包含数百万行的表,你应该从比我更擅长的人那里获得你的数据库建议。 :-) 不,甚至没有接近数百万 :) 它可能永远不会超过 20-25K 记录。但是,从 20K 中选择 20 行,按非键字段排序需要 0.7 秒,但如果我将该字段设为键,它几乎不会下降 - 0.02 和更少【参考方案2】:不要创建冗余或未使用的索引。但请务必创建您需要的索引来优化您运行的查询。
您可以根据查询选择任何表中的索引。每个查询可能使用不同的索引,因此仔细分析您的查询是值得的。请参阅我的演示文稿MENTOR Your Indexes。我还在我的书SQL Antipatterns: Avoiding the Pitfalls of Database Programming 中关于索引的章节中介绍了类似的信息。
没有关于多少索引太多的具体规则。在Oracle SQL Tuning Pocket Reference,作者马克·高锐说:
我的建议是避免规定网站不会超过一定数量的索引的规则。底线是所有 SQL 语句都必须以可接受的方式运行。总有办法实现这一目标。如果一个表需要10个索引,那么你应该在表上放置10个索引。
在Percona Toolkit:http://www.percona.com/doc/percona-toolkit/pt-duplicate-key-checker.html 和 pt-index-usage 中有几个很好的工具可以帮助您找到 mysql 的冗余或未使用的索引。
【讨论】:
【参考方案3】:这是一个很好的问题,每个使用 mysql 的人都应该知道答案。也经常被问到。这是其中一个答案很好的链接:
Indexing every column in a table
【讨论】:
【参考方案4】:简而言之,每个新索引都需要空间(尤其是如果您使用 InnoDB - 请参阅 this article 中的“集群的缺点”部分)并减慢插入、更新和删除的速度。
只有您可以决定您是否会在 SELECT 中获得加速以及使用它的频率是否值得。但无论您最终做出什么决定,请确保您的决定基于测量,而不是猜测!
附注带有 WHERE 的 INSERT、UPDATE 和 DELETE 也可以通过索引加速,但这是另一个主题...
【讨论】:
【参考方案5】:索引在磁盘空间中的成本通常是微不足道的。表更改时更新索引的额外写入成本通常适中。额外锁定的成本可能很高。
这取决于表的读写比率,以及索引实际用于加速查询的频率。
索引会占用磁盘空间来存储,并且需要时间来创建和维护。未使用的没有任何好处。如果查询有很多候选索引,则可能会因为让服务器为查询选择“错误”的索引而减慢查询速度。
使用这些因素来决定您是否需要索引。
通常可以创建永远不会使用的索引 - 例如,在只有两个可能值的(非空)字段上的索引几乎肯定是没用的。
您需要解释您自己的应用程序的查询,以确保经常执行的查询尽可能使用合理的索引,并且创建的索引不会超过所需的索引。
您可以通过以下链接获得更多信息: 对于 mysql: http://www.mysqlfaqs.net/mysql-faqs/Indexes/What-are-advantages-and-disadvantages-of-indexes-in-MySQL
对于 DB2: http://publib.boulder.ibm.com/infocenter/db2luw/v8/index.jsp?topic=/com.ibm.db2.udb.doc/admin/c0005052.htm
【讨论】:
【参考方案6】:索引可提高读取性能,但会增加大小并降低插入/更新性能。 8 个索引对我来说似乎有点太多了;但是,这取决于您通常多久更新一次表格
【讨论】:
【参考方案7】:假设 MySQL 来自标签,即使 OP 没有提及它。
您应该编辑您的问题并添加您正在执行order by
操作的事实(来自您发布到解决方案的评论)。 order by
操作也会减慢查询速度(与其他各种 mysql 操作一样),因为 MySQL 必须创建一个临时表来完成有序结果集(更多信息 here)。很多时候,如果数据集允许,我会拉取我需要的数据,然后在应用层排序,以避免这种惩罚。
最好的办法是解释你最常用的查询,并检查你的慢查询日志。
【讨论】:
以上是关于如果我创建索引,SQL 查询会快得多的主要内容,如果未能解决你的问题,请参考以下文章