以下是我会尝试的几件事,按照难度增加的顺序:
(更容易) - 确保你有正确的覆盖指数
CREATE INDEX ix_temp ON relations (relation_title, object_title);
鉴于您现有的模式,这应该最大化性能,因为(除非您的 mySQL 优化器版本真的很愚蠢!)它将最小化满足您的查询所需的 I/O 数量(不像索引是整个索引的相反顺序必须扫描),它将覆盖查询,因此您不必触摸聚集索引。
(有点难) - 确保你的 varchar 字段尽可能小
MySQL 上 varchar 索引的性能挑战之一是,在处理查询时,字段的完整声明大小将被拉入 RAM。因此,如果您有一个 varchar(256) 但仅使用 4 个字符,则在处理查询时您仍需支付 256 字节的 RAM 使用量。哎哟! 因此,如果您可以轻松缩小 varchar 限制,这应该会加快您的查询速度。
(更难) - 标准化
30% 的行只有一个字符串值,这显然是为了规范化到另一个表中,这样您就不会重复字符串数百万次。考虑规范化为三个表并使用整数 ID 将它们连接起来。
在某些情况下,您可以在幕后进行规范化并使用与当前表名称匹配的视图隐藏规范化......然后您只需让您的 INSERT/UPDATE/DELETE 查询知道规范化,但可以让您的 SELECT 单独.
(最难) - 散列你的字符串列并索引散列
如果规范化意味着更改太多代码,但您可以稍微更改架构,您可能需要考虑为字符串列创建 128 位哈希(使用MD5 函数)。在这种情况下(与规范化不同),您不必更改所有查询,只需更改 INSERT 和一些 SELECT。无论如何,你会想要散列你的字符串字段,然后在散列上创建一个索引,例如
CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);
请注意,您需要使用 SELECT 以确保您是通过哈希索引进行计算而不是拉入聚集索引(需要解析 object_title 的实际文本值才能满足查询)。
此外,如果relation_title 具有较小的varchar 大小但对象标题具有较长的大小,那么您可能仅对object_title 进行散列并在上创建索引(relation_title, object_title_hash)
。
请注意,此解决方案仅在这些字段中的一个或两个相对于哈希大小非常长时才有帮助。
另请注意,散列对区分大小写/排序规则有有趣的影响,因为小写字符串的散列与大写字符串的散列不同。因此,您需要确保在对字符串进行散列之前对其应用规范化 - 换句话说,如果您在不区分大小写的数据库中,则仅对小写进行散列。您可能还想从头或尾修剪空格,具体取决于您的数据库如何处理前导/尾随空格。