0

我有一个包含复杂查询的表,我正在寻找优化,我阅读了大多数关于 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 ) = 'N' 占总数的 10%。
    optional

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

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

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


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

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

2 回答 2

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它非常大(在千字节范围内)。

于 2013-09-02T15:23:11.467 回答
0

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

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

于 2013-09-02T15:24:41.943 回答