4

我们在很多地方都使用复合索引,而且效果很好。我们的平台有一个相对复杂的“报告生成器”,它可以根据用户的选择动态编写查询。我们根据常见查询选择索引,并且我们的复合索引通常与用户想要的内容很好地对齐。

例如(简化一吨),用户的报告将变成查询:

SELECT
  colA,
  colB,
  SUM(col1),
  SUM(col2)
FROM
  someTable
WHERE
  colA = "foo"
  AND colB = "bar"
  AND colC = "baz"
GROUP BY 1, 2;

表格看起来像:

CREATE TABLE someTable (
    id PRIMARY KEY,
    col1 data_type,
    col2 data_type,
    colA data_type,
    colB data_type,
    colC data_type,
    INDEX someIndex (colA,colB,colC)
);

我知道 MySQL 将无法在如下查询中使用该索引:

SELECT
  colA,
  colB,
  SUM(col1),
  SUM(col2)
FROM
  someTable
WHERE
  colB = "foo"
GROUP BY 1, 2;

我的问题是- MySQL 是否会使用复合索引进行如下查询:

SELECT
  colA,
  colB,
  SUM(col1),
  SUM(col2)
FROM
  someTable
WHERE
  colA != ""
  AND colB = "foo"
GROUP BY 1, 2;

当然,我知道我们可以在 上添加一个索引colB,但在这种情况下这不是一个好的选择。我在这里进行了简化以使问题更清楚。实际上,我们在这个表中有 100 列,并且不能在每列上添加索引和可能的列变化,所以我试图弄清楚我们是否可以利用我们已经拥有的东西来加快速度那些边缘情况查询。

希望我说得好。提前致谢 :)

4

2 回答 2

1

我的问题是 - MySQL 是否会使用复合索引进行如下查询:...

不,不会的。Not equals ( !=) 匹配不可索引,因此索引必须以 colB 开头才能使索引可用。如果您将索引从 (colA, colB, colC) 更改为 (colB, colA, colC),则该索引将可用于您提到的第一个查询和您正在询问的查询。

于 2020-06-07T17:50:23.220 回答
1
SELECT SUM(..), SUM(..)
    ...
    GROUP BY 1,2

没有意义。通常,一个GROUPs BY标量列,而不是聚合。去掉GROUP BY,你可能会得到相同的答案,而且得到的更快一点。

构建索引时,从用= (or IS NULL) 测试的列开始。

然后转到 any IN(constant list),因为它有时像=,有时像一个范围。

然后是一个“范围”——BETWEEN或任何不等式

因此对于

WHERE
  colA != ""
  AND colB = "foo"

colB应该是第一位的。因此 `INDEX(colB, colA)以该顺序适用于该查询(以及之前的查询)。

如前所述,INDEX(colB, colA, colC) 按该顺序 将适用于所有三个查询,但可能不适用于其他查询。

事项中的列顺序INDEX;中的顺序WHERE没有。综合指数的各个组成部分的基数无关紧要。

更长的讨论:http: //mysql.rjweb.org/doc.php/index_cookbook_mysql

于 2020-06-07T23:56:19.213 回答