【问题标题】:MySQL indexing char(1) columnsMySQL 索引 char(1) 列
【发布时间】:2013-09-02 15:16:16
【问题描述】:

我有一个需要优化的复杂查询表, 我阅读了大多数关于 MySQL 索引的文档.. 但在这种情况下我不确定 怎么办:

数据结构:

-- please, don't comment on the field types and names, it is outsourced project.

CREATE TABLE items(
  record_id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  solid CHAR(1) NOT NULL, -- only 'Y','N' values
  optional CHAR(1) NULL, -- only 'Y','N', NULL values
  data TEXT
 );

查询:

SELECT * FROM items
WHERE record_id != 88
AND solid = 'Y'
AND optional !='N'  -- 'Y' OR NULL

当然还有额外的连接和相关数据,但这是最大的过滤器。

在以下场景中:
- 200 000 多条记录,
- 10%(全部)solid = 'Y',
- 10%(来自全部)optional!='N',

什么是这个查询的好索引?
或更准确地说:

  • 第一个检查记录 != 88 是否会以任何方式减慢查询速度?
    (它只消除一个结果...?)

  • 哪个更快 (optional !='N') 或 ('optional' = 'Y' OR 'optional' iS NULL)
    如上所述optional = 'N' 占总数的 10%。

  • 对只有 2 个可能值的 CHAR(1) 列进行索引有什么特别之处吗?

  • 我可以使用这个索引(record_id、solid、optional)吗?

  • 我可以为特定值创建索引吗(solid = 'Y', optional !='N')?


根据@Jack 的要求,当前的 EXPLAIN 结果(总共 30 000 行,有 20 个结果):

+-------------+--------+--------------+---------+-- --------+------+--------+-----------+ |选择类型 |类型 |可能键 |关键 | key_len |参考 |行 |额外 | +-------------+--------+--------------+---------+-- --------+------+--------+-----------+ |初级 |范围 |初级 |初级 | 4 |空 | 16228 |使用位置 | +-------------+--------+--------------+---------+-- --------+------+--------+-----------+

【问题讨论】:

  • 仅供参考,optional != 'N''Y' OR NULL 不同。 NULL 很特殊,=!= 测试都失败了。
  • EXPLAIN SELECT ... 说什么?那将是第一个检查。
  • @Jack 不是真的,因为我现在有小数据集,而且只有 PK 索引。
  • 您可以模拟更大的数据集,不是吗? :)

标签: mysql


【解决方案1】:

这是一个有趣的问题。总体而言,您的查询的估计选择性约为 1%。因此,如果 100 条记录适合一个页面,那么您会假设仍然需要读取每个页面,即使有索引。因为记录是如此之小(取决于data),这很有可能。从这个角度来看,索引是不值得的。

在以下情况下,索引是值得的。第一种是当索引是覆盖索引时,这意味着您可以使用索引中的所有列满足查询。例如:

select count(*)
FROM items
WHERE record_id != 88 AND solid = 'Y' AND optional !='N'  -- 'Y' OR NULL

索引在solid, optional, record_id 上的位置。查询不需要回到原始数据页。

另一种情况是索引是主(或聚集)索引。数据按该顺序存储,因此获取有限数量的结果将减少查询的读取开销。这样做的缺点是更新和插入更昂贵,因为数据实际上必须移动。

在你的情况下,我最好的猜测是索引不会有用,除非data 非常大(在千字节范围内)。

【讨论】:

    【解决方案2】:

    您应该尝试将索引放在最能区分的列上。如果数据库在值之间平均分配,通常索引二进制列不是很有帮助。但如果您经常搜索的值只出现 10% 的时间,那么它可能是一个有用的索引。

    如果有任何列被索引,通常会在进行任何其他WHERE 处理之前检查它们。您在WHERE 子句中放置条件的顺序通常不相关。您可以使用EXPLAIN 找出查询使用的索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-22
      • 2011-02-22
      • 2016-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多