我们的很多用户、开发者和数据库***不时向我们的团队征询有关 EverSQL 的索引引荐算法。
所以,我们决议写一些这方面的内容。
本教程不会具体引见该算法的一切外部特征,而是要容易地阐明索引最主要的方面。别的,也是最主要的,我们将经过基于一套规矩而不是基于猜想来供给适用的示例,以便准确地索引表和查询。
本教程存眷的重点是 MySQL、MariaDB 和 PerconaDB 数据库。这些信息也可能与其他数据库供给商有关,但在某些状况下可能不会。
依据凡是的经历规矩,当测验考试优化你的 SQL 查询时,你可以按照以下步调构建复合索引:
起首列出你的查询中一切运用的表,并为查询中的每一个子查询创立一个自力的列表。假如你有一个包括 2 个 SELECT 子查询的 SELECT 查询,那你应当树立 3 个列表,每一个列表包括援用在此中的表。
在此进程完毕时,你可能会在每一个查询列表中为每一个这些表添加一个列的列表。
在你的任何索引中最右边的列应与查询相等比拟(如 age = 25)中的列适配。
你可以添加多个列,只需一切列与常量实行比拟相等便可。
那末,你应当选择一个列,这将是“范畴列(range column)”。MySQL 在每一个索引中只支撑一个范畴列。
因而,你应当运用范畴运算符(<>, >, <, IN(), BETWEEN, LIKE)来检查一切的比拟,并选择可以过滤最多行数的阿谁。
将该列给该表添加为你的索引中的下一列。
你可以在这里取得一些信息 —— 关于在范畴列之前添加相等列的来由(幻灯片由一名 MySQL 优化团队的成员编写)。
假如查询中不存在范畴列,你可以添加 GROUP BY 子句中的列。
假如查询中不存在范畴列,而且没有 GROUP BY 子句,则可以添加 ORDER BY 子句中的列。
在某些状况下,创立一个自力的索引来保管 ORDER BY 子句的列是成心义的,由于 MySQL 有时会选择运用它。请留意,虽然如斯,索引应当包括 ORDER BY 子句中的一切列,它们应当全体在 ORDER BY 子句顶用类似的次序(ASC / DESC)指定。这其实不能包管数据库的优化器会选择这个索引而不是 WHERE 复合索引,可是值得一试。
最初,从 SELECT 子句中添加相干的列,这可能答应 MySQL 运用索引作为掩盖索引。掩盖索引是包括过滤和查询子句中的一切列的索引。如许的索引答应数据库仅经过运用索引运转查询,而不需求拜访表。在很多状况下,这类办法明显更快。
我们经过一个示例来讲明:
SELECT id, first_name, last_name, age from employees where first_name = ‘John’ AND last_name = ‘Brack’ and age > 25 ORDER BY age ASC;
关于这个查询,我们将以添加 first_name 和 last_name 列Start,它们与等号运算符实行比拟。然后,我们将添加与范畴前提实行比拟的 age 列。这里不需求在 ORDER BY 子句索引,由于 age 列曾经在索引中了。最初异样主要的是,我们将从 SELECT 子句中添加 id 到索引以生成 covering 索引。
所认为了准确的索引这个查询,你应当添加以下索引:
employees (first_name, last_name, age, id)
以上是一个十分简化的伪代码算法,可让你为相当容易的 SQL 查询构建容易的索引。
假如你正在寻觅一种办法来完成这个进程的主动化,并盼望加强专有索引算法和查询优化的益处,你可以试用 EverSQL Query Optimizer,它为你做了一切沉重的任务。
我们搜集了一些顺序员和数据库***在编写查询和索引表时碰到的最多见的错误。
在大大多数状况下,MySQL 将不克不及在查询中为每一个表运用多个索引。
因而,当为表中的每列创立一个独自的索引时,数据库只能运用索引履行此中一个搜刮操作,而其他部分将光鲜明显较慢,由于数据库不克不及运用索引履行它们。
我们建议运用复合索引(本文稍后说明)而不是单列索引。
思索以下查询语句:
SELECT a, b FROM tbl WHERE a = 3 OR b = 8
在很多状况下,MySQL 将没法运用索引来使用 OR 前提,所以,此查询是不成索引的。
因而,我们建议防止这类 OR 前提,并思索将查询拆分为两部分,并联合 UNION DISTINCT 运用(或许最好运用 UNION ALL,以防你不晓得此中不会有任何反复的后果)
比如说,我把我的联络人德律风簿交给你,德律风簿是依照联络人的名字排序的,请求你找出德律风簿中有几多人名为“John”。你会接过德律风簿,说“没问题”。你将找到包括以 John 扫尾的一切名字的页面,并今后处Start计数。
如今,假定我改动了Task,并给你一个按联络人的姓氏排序的德律风簿,但请求你依然统计以“John”作为名字的一切联络人。你会怎样做? 异样的,数据库在这类状况下也会很难堪的。
如今让我们看看一个 SQL 查询来演示运用 MySQL 优化器时类似的行动:
SELECT first_name, last_name FROM contacts WHERE first_name = ‘John’;
具有索引的联络人(first_name, last_name)在这里是幻想的,由于索引从我们的挑选前提Start,然后在 SELECT 子句中以另外一个列完毕。
可是,具有反向索引的联络人(last_name,first_name)是相当没成心义的,由于数据库不克不及运用索引过滤,作为列,我们需求的是索引中的第二个,而不是第一个。
这个例子的结论是,索引中的列次序十分主要。
其它翻译版本 (1) 加载中当你试图优化你的 SQL 查询时,索引长短常成心义的,它可以明显地进步功能。
可是,这也有晦气的一面。你创立的每一个索引都应当坚持更新,并在数据库中发作更改时坚持同步。因而,关于数据库中的每一个 INSERT / UPDATE / DELETE,都应更新一切相干索引。此更新可能需求较长的工夫,特殊是关于大型的表/索引。
所以,除非你晓得你需求它们,不然不要创立索引。
别的,我们激烈引荐在某一段工夫内剖析一下数据库,搜刮任何可以删除的冗余索引。
本文中的一切译文仅用于进修和交换目标,转载请务必注明文章译者、出处、和本文链接。 2KB翻译任务按照 CC 协议,假如我们的任务有进犯到您的权益,请实时联络我们。2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务