【问题标题】:MySQL Optimization When Not All Columns Are Indexed并非所有列都被索引时的 MySQL 优化
【发布时间】:2012-07-25 19:18:49
【问题描述】:

假设我有一个包含 3 列和数千条记录的表,如下所示:

id # primary key
name # indexed
gender # not indexed

我想找到“所有叫 Alex 的男性”,即一个特定的名字和特定的性别。

幼稚的方式(select * from people where name='alex' and gender=2)在这里足够好吗?或者有没有更优化的方式,比如名字的子查询?

【问题讨论】:

    标签: mysql sql optimization innodb


    【解决方案1】:

    更好的方法是使用复合索引。

    CREATE INDEX <some name for the index> ON <table name> (name, gender)
    

    那么WHERE 子句可以同时用于姓名和性别。

    【讨论】:

    • 可能有用,但要避免额外索引的开销。如果只有少数人匹配任何名字,那就太夸张了。
    • @mahemoff - 硬盘相当便宜。此外,如果您仔细选择这些索引,它们也可以用于其他查询。
    • 集群的成本和复杂性很高,如果你到达了所有索引都不适合单个磁盘的地步。
    【解决方案2】:

    如果不能创建索引,或者表中有大量数据(或者即使有索引,但仍想加快步伐),重新排序通常会产生很大影响根据您分组在一起的数据的表格。

    我有一个查询要为我的部门汇总 KPI,尽管所有内容都已很好地索引,但提取的数据仍在搜索几张表。这意味着在查询将所有正确的行聚合在一起时会访问大量磁盘。我使用alter table tableName order by column1, column2; 对表进行了重新排序,查询从大约 15 秒到在 3 秒内返回数据。因此,数据的物理收集可能会产生重大影响 - 即使表已编入索引并且数据库确切知道在哪里得到它。安排数据以便数据库更容易获取所需的所有内容将提高性能。

    【讨论】:

    • 只对 MyISAM 表有用,并且发生在某个时间点;后续的插入/更新会慢慢分割这个顺序。
    【解决方案3】:

    假设您没有数千条记录,匹配​​名称,只有少数是真正的男性,name 上的索引就足够了。一般来说,您不应该索引具有很少carinality 的字段(只有 2 个可能的值意味着您将匹配 50% 的行,这不证明使用索引是合理的)。

    我能想到的唯一有用的例外是,如果您只选择姓名和性别,并且将它们都放入索引中,则可以执行index-covered query,这比按索引选择行和然后从表中检索数据。

    【讨论】:

      猜你喜欢
      • 2011-01-25
      • 1970-01-01
      • 2018-08-11
      • 1970-01-01
      • 2011-09-03
      • 2016-05-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多