应该在MySQL中使用/创建尽可能多的索引


Should one use/create as many indices as possible in MySQL?

我意识到,当为用于"ORDER BY"的列创建索引时,对MySQL查询的响应会变得更快,例如

SELECT username FROM table ORDER BY registration_date DESC

现在我想知道应该创建哪些索引来优化请求时间。例如,我经常使用以下查询:

SELECT username FROM table WHERE
    registration_date > ".(time() - 10000)."
SELECT username FROM table WHERE
    registration_date > ".(time() - 10000)."
    && status='active'
SELECT username FROM table WHERE
    status='active'
SELECT username FROM table ORDER BY registration_date DESC
SELECT username FROM table WHERE
    registration_date > ".(time() - 10000)."
    && status='active'
    ORDER BY birth_date DESC

问题1:我应该为前三种请求类型设置单独的索引吗?(即一个索引用于"registration_date"列,一个索引用作"status"列,另一列用于两者的组合?)

问题2:不同的索引是否分别用于"WHERE"answers"ORDER BY"?比如说,我有一个针对"status"answers"registration_date"列的组合索引,另一个仅针对"birth_date"栏的索引。我应该为这三列("status"、"registration_date"answers"birth_date")设置另一个组合索引吗?

索引或查询优化没有硬性规则。每一个案例都需要考虑和审查。

但是,一般来说,您可以而且应该向经常按WHERE语句排序或在WHERE语句中使用的列添加索引。(问题2的答案--否,ORDER BYWHERE可能使用相同的索引)是多列索引还是单列索引取决于查询频率。此外,您应该注意,单列索引可以由mySQL使用索引合并优化:进行组合

Index Merge方法用于检索具有多个范围的行扫描并将结果合并为一个。合并可以产生其基础的并集、交集或交集的并集扫描。这种访问方法合并来自单个表的索引扫描;它不合并跨多个表的扫描。

(更多阅读:http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html)

多列索引还要求您注意以这样的方式构建查询,即索引列的使用与索引中的列顺序匹配:

如果列不是最左边的列,MySQL就不能使用索引索引的前缀。假设您显示了SELECT语句此处:

从tbl_name中选择*col1=val1;选择*FROM tbl_name WHEREcol1=val1和col2=val2;

从tbl_name中选择*col2=val2;选择*FROM tbl_name WHEREcol2=val2和col3=val3;

如果(col1、col2、col3)上存在索引,则只有前两个查询使用索引。第三个和第四个查询确实涉及索引列,但(col2)和(col2,col3)不是的最左边前缀(第1栏,第2栏,第3栏)。

请记住,索引确实有自己的性能考虑因素——有可能"过度索引"一个表。每次插入记录或修改索引列时,都必须重新生成索引。这确实需要资源,而且根据表的大小和结构,在索引构建操作处于活动状态时,可能会导致响应能力下降。

使用EXPLAIN可以准确地了解查询中发生了什么。分析、实验,不要过度。鸟枪式方法不适合数据库优化。

文档

  • MySQL EXPLAIN-http://dev.mysql.com/doc/refman/5.0/en/explain.html
  • MySQL如何使用索引-http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
  • 索引合并优化-http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html

引用本页:

[索引]会减慢您的更新和插入速度。

这是你必须计算的代价。要优化表,您应该在最有可能应用条件的列中只放置索引-索引越多,数据更改操作就越慢。从这个意义上说,我个人认为创建组合索引没有多大好处——如果你为3列创建了所有7种可能的索引排列,那么你肯定会比只为3列使用3个索引更拖累你的更新和插入(甚至这也是有争议的)。另一方面,如果数据被编辑得太多,SELECTed少很多,那么索引确实可以帮助您加快速度。

需要考虑的其他因素(再次引用上页):

如果你的表很小[…],使用索引比把它排除在外,让它扫描表更糟糕。索引实际上只在有很多行的表中才有用。

是的,最好在您经常使用的列上设置索引,用于order by子句和where子句。

但要注意:如果你有索引,那么UPDATES、INSERTS和DELETE会减慢速度。

这是因为在这样的操作之后,索引也必须更新。

因此,根据经验:如果您的应用程序是阅读密集型的,请在您认为有帮助的地方使用索引。

如果您的应用程序经常更新数据,请小心,因为索引可能会导致更新速度变慢。

当你有疑问时,你必须简单地把手弄脏,并研究EXPLAIN的结果。

http://dev.mysql.com/doc/refman/5.6/en/explain.html

对于前两个示例,您可以用一个索引来满足它们:{registration_date,status}。这样的索引可以支持对第一个项目(registration_date)或对这两个项目的过滤器。

然而,这不仅仅是为了地位。关于地位的问题是,地位有多选择性。也就是说,有多大比例的记录具有状态="活动"。如果这是一个很高的比例(因此,平均而言,每个数据库页面都会有一个活动记录),那么索引可能没有多大帮助。

by的订单比较棘手。我不知道mysql是否为此目的使用索引。通常,使用索引对整个记录进行排序的效率低于仅对记录进行排序。使用索引会导致对页面中记录的随机访问模式,这可能会导致大于页面缓存的表出现重大性能问题。

在选择语句上使用解释函数来确定连接的速度减慢的地方(引用的行越多,速度就越慢)。然后将索引应用于这些列。

EXPLAIN SELECT * FROM table JOIN table 2 ON a = b WHERE conditions;