我有一个包含复杂查询的表,我正在寻找优化, 我阅读了有关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',
这个查询有什么好的索引?
或者更准确地说:
执行第一次检查记录!= 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 | +-------------+-------+--------------+---------+---------+------+-------+-------------+
答案 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
找出查询使用的索引。