【问题标题】:How can I create an index on the substring of a column?如何在列的子字符串上创建索引?
【发布时间】:2021-03-14 16:49:30
【问题描述】:

我有一个包含键值对的表,我希望它能够有效地搜索:

SELECT * WHERE meta_key = "User ID" AND meta_value = "123userId";

但是,由于遗留要求,键和值 NVARCHAR 存储可能分别高达 255 和 1000 个字符。对如此大的列进行索引不仅成本高昂,而且完全受限于某些数据库类型。

我相信 MySQL 有一个系统允许通过 LEFT 样式的子字符串进行索引,如下所示:

CREATE INDEX ix_metadata_indexing_key_value ON metadata_indexing(meta_key, meta_value(255));

...但是我们的系统必须支持 MySQL、MSSQL 和 Oracle 这三个。这是解决这个问题的正确方法吗?如果是,我如何在 MSSQL 和 Oracle 上创建类似的索引?

【问题讨论】:

  • 如果您需要一个解决方案,您可能需要为每个供应商提供不同的解决方案。这三个人都使用非常不同的方言。对于 SQL Server,我建议添加一个 PERSISTED 计算列并为其编制索引;那么您可以改为在WHERE 中查询。不过,考虑到您只想要 LEFT 一侧,LIKE 也可能是 sargable WHERE YourColumn LIKE '123userid%'; 将在您的列 YourColumn 上使用索引。
  • 另外值得注意的是,ANSI SQL 标准中根本没有关于索引的内容。每个供应商都发明了自己的专有语法和索引功能。您需要考虑Adapter Pattern,因为没有适用于所有供应商实现的语法。
  • 这听起来既像过早优化又像XY problem。你觉得这样一个有限的索引有用吗?
  • “听起来像是 x-y 问题”。听起来也像是 EAV 设计,这是强加给 RDBMS 世界的最糟糕的概念之一。
  • 正如其他人所说,不存在与数据库无关的解决方案。对于 Oracle,我会考虑基于函数的索引。

标签: mysql sql sql-server oracle indexing


【解决方案1】:

如果您谈论的是 WordPress,那么该索引只是解决方案的一部分。进入postmeta 时,您需要一个复合 post_id 开头。更多推荐here.

另外,如果数据足够可预测,您也许可以将LONGTEXT 替换为更文明的东西,例如VARCHAR(150)。做SELECT MAX(LENGTH(meta_key)), MAX(LENGTH(meta_value)) FROM post_meta;

(我也是,泛 EAV。尤其是 WP 的糟糕实现。)

【讨论】:

  • 不,不是 WordPress 的东西,完全定制
  • @Arachin - 好吧,检查我的链接,看看他们是否也弄乱了索引。
【解决方案2】:

正如@Larnu 建议的那样,我们最终得到了一个新的计算meta_value_short 列,需要为每种数据库类型单独生成。查询时...

如果长度为 255 或更少:只需与 meta_value_short 比较。

否则:先将LEFT(value, 255)meta_value_short进行比较,然后再与meta_value进行比较。


计算列定义如下:

MSSQL: ALTER TABLE [metadata_indexing] ADD meta_value_short AS (SUBSTRING(meta_value, 1, 255))

MySQL: ALTER TABLE metadata_indexing ADD meta_value_short VARCHAR(255) AS (SUBSTRING(meta_value, 1, 255));

甲骨文: ALTER TABLE metadata_indexing ADD meta_value_short AS (SUBSTR(meta_value, 1, 255));

【讨论】:

    猜你喜欢
    • 2021-04-07
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 2012-01-17
    • 2012-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多