2

假设我有一张桌子50 columns。我想做类似的事情:

SELECT * FROM table WHERE column1=value1 OR column2=value2 OR ...

我怎样才能有效地做到这一点?

  1. indexes我可以在许多/所有列中添加一堆或一个索引。这会有帮助吗?

  2. 我可以创建一个secondary table带有列(id, field_name, field_value

  3. 我还可以做些什么?

有关更多信息:

  • 行添加非常频繁,但之后很少编辑。
  • 行在添加后被多次选择(可能几十但可能不是数百)。
  • 表有 100,000 多行,表扫描太慢。
  • 具体来说,给定一行,我想在 ANY 列上查找与该行匹配的所有行。
4

2 回答 2

0

暂且讨论更改数据库设计...


组合索引(查询中引用的许多或大部分列的索引)对您的查询没有帮助,它有一堆OR'dcolN = 'foo'谓词。MySQL 不会使用该索引来满足您的查询。即使要使用索引,基础表中的其他列仍然需要对每一行进行检查,因此 MySQL 很可能只是访问所有数据页而根本不使用索引。(如果您的查询中碰巧有 GROUP BY 或 ORDER BY,MySQL 可能能够使用该索引来优化这些操作,特别是如果它是一个“覆盖”索引,其中包含您的查询引用的每一列。

另一方面,如果您在每一列(作为索引中的前导列)上都有一个单独的索引,并使用 进行检查OR colN = 'foo' OR colN = 'bar',则 MySQL 可能会考虑为您的查询使用“索引合并”计划。

但它必须是每一列的索引。如果您的查询甚至只检查一个不是任何索引中的前导列的列,那么 MySQL 将别无选择,只能检查表中的每一行。因此,在“许多”列上设置单独的索引将无助于您的查询,因为很可能不会使用任何索引。

即使您确实为每一个被引用的大量列都有一个单独的索引,MySQL 对返回的总行数(从每个索引组合)的估计也可能太大,并且 MySQL 可能会决定“索引合并”太昂贵了,而是选择全表扫描。


总而言之,帮助您查询的索引只有两种选择(而且它们都不是一个真正好的选择):

1) 具有可用于满足 GROUP BY 或 ORDER BY 子句的前导列的“覆盖索引”(避免“使用文件排序”操作)

OR colN = 'literal'2) 由查询中的谓词检查的每一列(作为前导列)上的单独索引

但同样,这些都不是一个好的选择。

于 2012-12-21T00:06:23.210 回答
0

当您遇到这样的场景时,它通常表明可能存在规范化表格的空间(您的场景 B)。如果没有关于您的列实际包含哪些数据以及您的整体表访问模式是什么的进一步信息,将很难知道。

话虽如此,在没有任何类型的表结构更改的情况下,您只需要在可能要查询的每一列上都有一个索引,以防止全表扫描。

于 2012-12-20T23:27:55.597 回答