【问题标题】:Does the order of columns matter in a multi-column index if there is no value in the WHERE clause如果 WHERE 子句中没有值,列的顺序在多列索引中是否重要
【发布时间】:2015-03-03 17:11:46
【问题描述】:

我了解需要多列索引,并且索引顺序在请求中很重要,例如

    SELECT product_id 
      FROM order_detail 
     WHERE order_id in (1, 2, 3)

但是,当WHERE 子句中没有值时,我无法弄清楚多列索引和索引顺序的必要性。

  1. 我相信只有在 WHERE 子句中指定了一个值时才使用多列索引(我可能错了)。因此,为了“优化”表 order_detail 和下面的请求,我应该在 product_id 和 order_id 上创建一个多列索引 还是应该创建两个独立的索引,一个在 order_id 上,一个在 product_id 上:

    SELECT O.order_id, P.product_name 
      FROM order_detail OD, order O, product P 
     WHERE OD.order_id = O.order_id 
       AND P.product_id = OD.product_id    
    
  2. 如果在 WHERE 子句中的两列上进行搜索时仍然需要多列索引,即使其中没​​有值,那么给多列索引的正确顺序是什么? 关于上面 order_detail 表的示例,我应该使用 (order_id, product_id) 还是应该使用 (product_id, order_id)?当WHERE 子句中没有值时,顺序是否重要?

非常感谢您的帮助。

【问题讨论】:

    标签: mysql


    【解决方案1】:

    列的顺序很重要。 MySQL 可以使用索引(product_id, order_id) 进行以下操作:

    • 哪里 product_id = 123
    • 其中 product_id = 123 AND order_id = 456

    但不适用于:

    • 哪里 order_id = 123

    另外值得注意的是,MySQL 可以选择不使用索引。例如,如果 1000 个订单中只有 10 个不同的产品,那么 MySQL 可以忽略索引。

    我建议首先放置基数较高的列。或者更好的是,创建两个索引(product_id, order_idorder_id, product_id)并让 MySQL 决定使用哪一个。

    【讨论】:

      【解决方案2】:
      1. 优化WHERE 子句时只能使用一个索引。因此,如果您正在测试多列,并且想要获得最佳性能,则应使用包含所有(或大部分)列的多列索引。如果您创建两个单独的索引,它将只使用其中一个来优化 WHERE 条件的那一部分,然后它必须在这些行中进行扫描以匹配另一个条件。

      2. 多列索引可用作前缀中任何列集的索引。因此,如果您在(col1, col2, col3) 上有一个索引,它也可以作为col1(col1, col2) 上的索引。如果你在(order_id, product_id) 上有一个索引,它也可以用来优化第一个查询。如果您还希望能够优化仅使用 product_id 的查询,请在该列上创建一个附加索引。相反,如果您在 (product_id, order_id) 上有一个索引,则需要在 order_id 上创建一个单独的索引来优化第一个查询。

      【讨论】:

      • 谢谢。关于第二个查询,如果我在 (product_id, order_id) 上有一个索引,它的行为是否与 (order_id, product_id) 相同?如果 WHERE 子句中没有值,索引中的顺序是否重要?
      • 我以为我很清楚,顺序很重要。多列索引也是前缀列的索引。它不是任何不是前缀的列的索引。所以(product_id, order_id) 本身不是order_id 列的索引,而是product_id 列本身的索引。
      • 我不确定您所说的“WHERE 没有价值”子句是什么意思。在您的第二个查询中,您在 WHERE 子句中有值,它们是您要加入的表中的列。索引用于优化加入策略。
      【解决方案3】:

      您为什么要关注 WHERE 子句中给定的列是否有文字值?就此而言,您为什么要全神贯注于 WHERE 子句?您的第二个查询可以在没有 WHERE 子句的情况下重写,并且仍然会给出相同的结果:

      SELECT
          O.order_id,
          P.product_name
      FROM
          order_detail AS OD
          JOIN order AS O ON OD.order_id = O.order_id
          JOIN product AS P ON P.product_id = OD.product_id
      

      引擎是在查找查询中指定的字面值,还是从连接表中的行中查找值并不特别重要。它将尝试选择一种策略,使连接表的过程变得高效。

      【讨论】:

      • 谢谢,但是在 order_detail 中,我应该创建一个多列索引还是 2 个单独的索引(一个在 product_id 上,一个在 order_id 上)?
      猜你喜欢
      • 2017-12-19
      • 1970-01-01
      • 1970-01-01
      • 2012-07-11
      • 1970-01-01
      • 2011-01-18
      • 2014-08-10
      • 2011-03-05
      • 1970-01-01
      相关资源
      最近更新 更多