MySQL索引char(1)列

时间:2013-09-02 15:16:17

标签: mysql

我有一个包含复杂查询的表,我正在寻找优化, 我阅读了有关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+记录,
  - solid ='Y',来自所有人的10%   - optional!='N',

的10%(来自所有人)

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

  • 执行第一次检查记录!= 88以任何方式查询速度慢吗? (它只会导致一个结果......?)

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

  • 是否有任何特殊的索引CHAR(1)列只有2个可能的值?

  • 我可以使用此索引(record_id,solid,optional)?

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


正如@Jack所要求的那样,当前 EXPLAIN 结果(总共30 000行,结果为20):

+-------------+-------+--------------+---------+---------+------+-------+-------------+
| select_type | type  | possible_key |   key   | key_len | ref  | rows  |    Extra    |
+-------------+-------+--------------+---------+---------+------+-------+-------------+
| PRIMARY     | range | PRIMARY      | PRIMARY |       4 | NULL | 16228 | Using where |
+-------------+-------+--------------+---------+---------+------+-------+-------------+

2 个答案:

答案 0 :(得分:3)

这是一个有趣的问题。总的来说,您的查询估计选择性约为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非常大(以千字节为单位)。

答案 1 :(得分:0)

您应该尝试将索引放在最容易受歧视的列上。如果数据库在值之间平均分配,通常索引二进制列并不是很有用。但是,如果您经常搜索的值仅出现10%的时间,则它可能是一个有用的索引。

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