建立索引的目的是为了加速查询,所以请确保索引能在一些查询中被用上。如果一个索引不会被任何查询语句用到,那这个索引是没有意义的,请删除这个索引。使用组合索引时,需要满足最左前缀原则。
例如假设在列 title, published_at 上新建一个组合索引索引:
CREATE INDEX title_published_at_idx ON books (title, published_at);
下面这个查询依然能用上这个组合索引:
SELECT * FROM books WHERE title = 'database';
但下面这个查询由于未指定组合索引中最左边第一列的条件,所以无法使用组合索引:
SELECT * FROM books WHERE published_at = '2018-08-18 21:42:08';
例如假设在时间类型的列 published_at 上新建一个索引:
但下面查询是无法使用 published_at 上的索引的:
SELECT * FROM books WHERE YEAR(published_at)=2022;
可以改写成下面查询,避免在索引列上做函数计算后,即可使用 published_at 上的索引:
也可以使用表达式索引,例如对查询条件中的 YEAR(published_at) 创建一个表达式索引:
然后通过 SELECT * FROM books WHERE YEAR(published_at)=2022; 查询就能使用 published_year_idx 索引来加速查询了。
例如下面查询只需扫描索引 title_published_at_idx 数据即可获取查询列的数据:
但下面查询语句虽然能用上组合索引 (title, published_at), 但会多一个回表查询非索引列数据的额外开销,回表查询是指根据索引数据中存储的引用(一般是主键信息),到表中查询相应行的数据。
SELECT * FROM books WHERE title = 'database';
查询条件使用 !=,NOT IN 时,无法使用索引。例如下面查询无法使用任何索引:
使用 LIKE 时如果条件是以通配符 % 开头,也无法使用索引。例如下面查询无法使用任何索引:
SELECT * FROM books WHERE title LIKE '%database';
当查询条件有多个索引可供使用,但你知道用哪一个索引是最优的时,推荐使用 来强制优化器使用这个索引,这样可以避免优化器因为统计信息不准或其他问题时,选错索引。
例如下面查询中,假设在列 id 和 列 title 上都各自有索引 id_idx 和 title_idx,你知道 id_idx 的过滤性更好,就可以在 SQL 中使用 USE INDEX Hint 来强制优化器使用 id_idx 索引。
查询条件使用 表达式时,后面匹配的条件数量建议不要超过 300 个,否则执行效率会较差。