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

时间:2012-07-27 15:22:20

标签: php mysql optimization query-optimization

我意识到,当为“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”和“ORDER BY”?比如说,我有一个列为“status”和“registration_date”的组合索引,另一个索引仅用于“birth_date”列。我应该为三列设置另一个组合索引(“status”,“registration_date”和“birth_date”)吗?

5 个答案:

答案 0 :(得分:3)

索引或查询优化没有严格的规则。每个案例都需要考虑和审查。

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

  

索引合并方法用于检索具有多个范围的行   扫描并将其结果合并为一个。合并可以产生   工会,交叉点或其基础的交叉点   扫描。此访问方法合并来自单个表的索引扫描;它   不会跨多个表合并扫描。

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

多列索引还要求您注意构造查询,使得索引列的使用与索引中的列顺序匹配:

  

如果列不形成最左边的列,则MySQL无法使用索引   索引的前缀。假设您显示了SELECT语句   这里:

     

SELECT * FROM tbl_name WHERE col1 = val1; SELECT * FROM tbl_name WHERE   col1 = val1 AND col2 = val2;

     

SELECT * FROM tbl_name WHERE col2 = val2; SELECT * FROM tbl_name WHERE   col2 = val2 AND col3 = val3;

     

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

请记住,索引DO具有自己的性能考虑因素 - 可以对表进行“过度索引”。每次插入记录或修改索引列时,都必须重建索引/索引。这确实需要资源,并且根据表的大小和结构,它可能会导致索引构建操作处于活动状态时响应速度降低。

使用EXPLAIN确切了解您的查询中发生了什么。分析,实验,不要过度。霰弹枪方法不适合数据库优化。

<强>文档

答案 1 :(得分:1)

引用this page

  

[指数]会降低您的更新和插入速度。

这是你必须计算的权衡。要优化表格,您应该将索引放在最有可能应用条件的列中 - 您拥有的索引越多,数据更改操作就越慢。从这个意义上说,我个人认为创建组合索引并没有太大的优点 - 如果你为3列创建索引的所有7种可能的排列,你肯定会对你的更新和插入产生更多的拖累,而不仅仅是使用3列的3个索引(甚至可以说是有争议的)。另一方面,如果数据被编辑得太多,很多SELECT更少,那么索引可以真正帮助你加快速度。

需要考虑的其他事项(再次引用上面的内容):

  

如果你的桌子非常小,那么使用索引要比把它留下来更糟糕,让它进行表扫描。索引实际上只对具有大量行的表格派上用场。

答案 2 :(得分:1)

是的,最好在您经常使用的列上添加索引,包括order by和where子句中的索引。

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

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

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

如果您的应用程序经常更新数据,请注意,因为索引可能会变慢。

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

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

答案 3 :(得分:1)

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

但是,它不仅适用于状态。关于地位的问题是地位的选择性。也就是说,有多少记录具有status =“active”。如果这个比例很高(因此,平均而言,每个数据库页面都会有一个活动记录),那么索引可能无济于事。

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

答案 4 :(得分:0)

在select语句中使用explain函数来确定连接速度减慢的位置(引用的行越多,它就越慢)。然后将索引应用于这些列。

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