MySQL InnoDb:如何通过所需的列来解决不同顺序的速度问题

时间:2014-01-10 20:38:26

标签: mysql indexing

我有一个相当简单的SQL语句,如下所示:

SELECT * FROM table WHERE col1 = 'x' 
    AND col2 = 'y' AND col3 = 'z' 
    ORDER BY col4 LIMIT 0,40

如果我有col1_col2_col3的索引,则查询执行时间为4.2秒(可怕)。 如果我有col1_col2_col3_col4的索引,则执行时间为0.003秒(太棒了!)。

因此,将ORDER BY列引入索引会产生一个差异。

现在提出问题

我需要能够在col4到col14上进行排序(不是在一个查询中,在10种不同的情况下,取决于用户选择的排序顺序),即10种不同的ORDER BY。

我真的需要为此创建10个索引吗?这甚至可以建议吗?具有那么多索引的插入量是否会减慢?

有什么想法?感谢。

1 个答案:

答案 0 :(得分:2)

是的,你需要10个不同的索引。

可以这样想:你在第1,2和3列中搜索匹配三个特定值的行。所以匹配行的集合基本上是绑定的。因此,您所需的排序顺序可以是打破平局列,必须是索引的第四列

您不能使用一个索引在索引的给定位置按多个列排序。

在数据库中维护索引需要花费一些开销。索引越多,开销越大。但是要记住一些事情:

  • 通常,索引不会导致开销的“数量级”。记住,一个数量级意味着10倍。人们夸大了指数的成本,然后担心应该避免指数。

    在一本书The Art of SQL中,作者在添加索引时测试了性能开销。他发现开销没有随索引数量线性增加。开销在大致对数曲线中减小。换句话说,更多的索引确实有更多的开销,但索引数量的2倍不会花费2倍。这是有道理的,因为更新索引是对数复杂度的操作,而不是线性复杂性。

  • 在INSERT / UPDATE / DELETE上发生开销。 SELECT也有轻微的开销,因为优化器可能必须分析更多的索引组合。但这通常不是一大瓶颈。通常,写入的开销比读取的开销更重要。

  • InnoDB还具有加速写入二级索引的优化,称为change buffering。这是自动发生的,它通过排队更改然后逐渐将它们合并到实际索引中而有利于写入。

  • 因此,开销量取决于您的读写比率是多少。没有人能够准确地告诉您索引在开销方面的成本,因为每个应用程序的答案都不同。

  • 索引也有助于UPDATE和DELETE。任何带有WHERE子句或ORDER BY子句的SQL语句都将使用索引来避免执行表扫描并避免进行昂贵的排序。有些人声称“索引有助于读取但会惩罚写入”,但这是过于简单化。

  • 您刚观察到SELECT从4.2秒提高到0.0003秒,其中 提升了4个数量级。而索引可能导致写入成本加倍,甚至10倍(仅一个数量级)。您必须决定是否值得为您的申请进行权衡。

    例如,如果你有频繁的SELECT语句需要快10,000倍,并且当你的频繁写入需要0.1秒而不是0.01秒时你可以容忍它,那么它似乎是一个很好的权衡。