【问题标题】:How to index a MySQL table when both >= and <= is used?当同时使用 >= 和 <= 时如何索引 MySQL 表?
【发布时间】:2013-08-12 08:07:05
【问题描述】:

假设您有这样的查询,

select ID, REGION, START, END from COORD_SYSTEM 
where REGION=? and TYPE=? and START >= ? and END <= ?;

假设这个表有大约 50,000 行。 REGION 列有 500 个不同的值,TYPE 列有 50 个不同的值。 ID 列是主键。

索引表的最佳方法是什么?由于 >= 和 覆盖索引。这里有几个选项:

  1. 在 COORD_SYSTEM (REGION, TYPE) 上创建索引
  2. 在 COORD_SYSTEM(REGION、TYPE、START)上创建索引
  3. 在 COORD_SYSTEM(REGION、TYPE、START、END)上创建索引

更新 - 这是解释语句:

          id: 1
  select_type: SIMPLE
        table: COORD_SYSTEM
         type: range
possible_keys: indx_A
          key: indx_A
      key_len: 50
          ref: NULL
         rows: 590
        Extra: Using where
1 row in set (0.00 sec)

【问题讨论】:

  • 我想说3应该更好,你有没有在一些有大量行的测试数据上试过?
  • 使用选项 3 它应该只能在索引上运行。选项 2 和 3 也应该具有相同数量的扫描行。你能发布解释的吗?
  • 你试过create index on COORD_SYSTEM (REGION, TYPE, START, END desc)吗??
  • select_type 信息不够,请告诉我们Extra 列中的值(最后一列)
  • @RandomSeed 确定我添加了说明语句。

标签: mysql


【解决方案1】:

没有理由不能将覆盖索引与范围运算符一起使用。挑战(对于非覆盖索引)是优化器可能认为如果您的范围很大,则完全扫描可能会导致更少的页面读取,并且索引不会用于您的某些查询。同样,对于某些参数值,如果覆盖索引并不比扫描某些参数集好多少,优化器可能会选择进行全扫描。

因此,鉴于问题中的描述,实际上不可能为所有情况提供最佳解决方案。

我倾向于做这样的事情是:

  • 创建数据库副本
  • 猜猜哪个索引可能完成这项工作,并创建该索引。
  • EXPLAIN 具有不同大小范围的几个查询(如果您没有覆盖查询,则更多范围需要更多 I/O 才能返回表数据,因此您应该尝试常见范围大小和异常值)
  • 删除索引并尝试另一个索引,可能使用不同的覆盖索引,列的顺序不同

您甚至可以选择创建两个或多个包含不同顺序字段的覆盖索引,假设您运行此查询的次数比相应的INSERTs 或UPDATEs 多得多,并且索引的大小不是t 磁盘空间使用的一个因素。

【讨论】:

  • 谢谢!关于重新排序索引字段的最后一个提示非常有用:它大大减少了检查的行数。
【解决方案2】:

您可以将索引视为一种按索引列中的值对行进行预排序的方法。索引可用于与&gt;=&lt;= 进行比较,方法与= 相同。

您的选项 3可能是最好的索引,因为所有WHERE 条件都可以通过查看索引来检查。它是否实际上是最佳索引取决于您的数据集,因为例如,如果您的大多数记录具有非常大的 end 值,则所有记录都将满足条件 WHERE end &lt;= ? 和索引在该字段上几乎没有用处(优化器可以决定不对该字段使用索引,因为它会导致没有“投资回报”的开销)

【讨论】:

    【解决方案3】:

    您正在寻找的是 BETWEEN 命令,您不需要为此设置 START 和 END。您只需 1 个表格行即可。

    SELECT ID, REGION, START, END from COORD_SYSTEM WHERE REGION=? and TYPE=? BETWEEN 100 and 200;
    

    【讨论】:

    • No... 从查询中可以看出 START 和 END 是表中的两个单独的列,我传递了两个单独的参数进行比较。
    猜你喜欢
    • 1970-01-01
    • 2011-07-30
    • 1970-01-01
    • 2011-11-23
    • 1970-01-01
    • 2012-12-21
    • 2014-07-07
    • 1970-01-01
    • 2014-06-30
    相关资源
    最近更新 更多