求求了,数据库索引就该这么建!

戳上方蓝字“Java知音”关注我

前言

网上各种文档教程看了一堆,总是在说“建索引”、“建索引”,各种索引类型,可为啥我建了索引,它还是慢呢!

别着急,耐心看完,你一定有所收获。

正文

废话不多说,直接上要点。

1. 在经常用于查询条件的字段上创建索引

这类字段在where条件里面经常用到,如果不加索引,每次查询都要全表扫描,随着数据量增长查询效率迅速下降。加了索引可以避免扫描大部分数据。

CREATE INDEX idx_status ON table_name(status);
SELECT * FROM table_name WHERE status = 1;

以下条件查询大概率会走索引:

  • 等值查询: 例如 WHERE column_name = 'value'

  • 范围查询: WHERE column_name BETWEEN 'value1' AND 'value2' 或 WHERE column_name > 'value',这种查询也可能会走索引,特别是当被索引的列的范围较小时。

  • 部分模糊查询:主要是右模糊查询,例如 WHERE column_name LIKE 'value%'

  • 排序和分组:当查询涉及到 ORDER BYGROUP BY 子句时,如果被排序或分组的列上有索引,数据库可能会选择使用索引来加速查询。

  • 连接查询: 在连接查询中,如果连接的字段有索引,数据库可能会利用这些索引来优化查询。

求求了,数据库索引就该这么建!
2. 对于查找单条记录的字段创建唯一索引

唯一键对应的数据只有一条,要找到这条记录只能全表扫描,数据量大会很慢。加唯一索引可以直接定位到记录。

CREATE UNIQUE INDEX idx_uid ON table_name(uid);
SELECT * FROM table_name WHERE uid = 123;
3. 在表与表的关联键上创建索引

表JOIN时依靠这个键进行关联,如果不索引就会扫描全表去对比键值,数据量越大关联效率越低。加索引可以快速匹配关联键值。

CREATE INDEX idx_post_id ON comments(post_id);
SELECT * FROM comments WHERE post_id = 12345;
4. 在经常需要排序的字段建立索引

排序时如果不加索引,需要全表扫描获取所有记录再排序,数据量大时排序开销巨大。索引可以按序直接读取记录,避免全表扫描。

CREATE INDEX idx_create_time ON table_name(create_time);
SELECT * FROM table_name ORDER BY create_time DESC;
5. 对于频繁用于left join的表的关联键创建索引

左连表时都会全表扫描右表去匹配关联条件,数据量大时非常慢。加索引可以快速过滤出匹配的记录。

CREATE INDEX idx_user_id ON table_a(user_id); 
SELECT * FROM table_a
LEFT JOIN table_b ON table_a.user_id = table_b.user_id;
6. 在表的数据量巨大时对主键创建索引

主键默认会有索引,如果去掉索引,增删改查所有操作都会变慢,特别是主键查询需要全表扫描。

CREATE INDEX idx_id ON large_table(id);
7. 对于组合查询的字段建立联合索引

单列过滤效果不好时,加联合索引可以多列组合过滤提升效率。

这里的使用场景太广泛,请注意。

求求了,数据库索引就该这么建!

假设我们有一个示例表格products,包含以下列:

  • product_id – 产品ID(唯一标识)
  • product_name – 产品名称
  • category – 产品类别

我们希望对product_name列进行右模糊查询,以找到以特定字符串结尾的产品名称。

在这种情况下,我们可以创建一个联合索引,将category列放在product_name之前。这是因为MySQL和一些其他数据库系统的索引优化算法能更好地利用联合索引的前缀部分。下面是创建联合索引的示例 SQL 语句:

CREATE INDEX idx_product_name_category ON products (product_name, category);

以上命令将在products表上创建一个名为idx_product_name_category的联合索引,该索引涵盖了product_namecategory两列。

现在,假设我们要执行右模糊查询,找到以字符串”xyz”开头且属于某个特定类别的产品名称:

SELECT product_name
FROM products
WHERE product_name LIKE 'xyz%' AND category = 'some_category';

在这个查询中,MySQL可以有效地利用联合索引idx_product_name_category,首先根据category过滤记录,然后在满足category条件的记录中使用联合索引来加速product_name的右模糊查询。

8. 在文本字段创建前缀索引

上面一点其实说到了模糊查询的问题,针对模糊查询,有几点需要提及:

  • 左模糊查询: 如果LIKE查询的模式以通配符开头(例如:’%abc’),大多数数据库系统将无法使用普通B-tree索引来加速查询。这是因为B-tree索引对于模式开头的通配符查询效果较差。

  • 右模糊查询: 如果LIKE查询的模式以通配符结尾(例如:’abc%’),大多数数据库系统可以使用普通B-tree索引来加速查询。这是因为B-tree索引可以快速找到匹配模式前缀的记录。

  • 左右模糊查询: 如果LIKE查询的模式既以通配符开头又以通配符结尾(例如:’%abc%’),通常无法有效使用普通B-tree索引。

  • 不以通配符开头或结尾的模糊查询: 如果LIKE查询的模式不以通配符开头或结尾(例如:’abc’或’abcde’),并且不包含其他特殊字符(如转义字符“),大多数数据库系统可以使用普通B-tree索引来加速查询。

因此在给文字字段创建索引后,应尽量:

要使LIKE查询走索引,可以考虑以下方法:

  • 右模糊查询: 如果可能,将通配符放在模式的末尾,例如:’abc%’。这样,数据库系统可以使用B-tree索引来快速定位匹配前缀的记录。

  • 使用其他索引类型: 一些数据库系统支持针对模糊查询的其他特殊索引类型。例如,PostgreSQL支持Trigram索引,用于处理模糊查询。

  • 搜索引擎: 使用外部搜索引擎,比如ELasticSearch等

CREATE INDEX idx_title_prefix ON table(title(10));
SELECT * FROM table WHERE title LIKE 'key%';

收尾

讲到这里其实也差不多了,但还有一个至关重要的问题,怎样才能知道索引有没有生效?

这就得用到EXPLAIN大法了。

来源:juejin.cn/post/7260727363876241465

后端专属技术群

构建高质量的技术交流社群,欢迎从事编程开发、技术招聘HR进群,也欢迎大家分享自己公司的内推信息,相互帮助,一起进步!

文明发言,以交流技术职位内推行业探讨为主

广告人士勿入,切勿轻信私聊,防止被骗

求求了,数据库索引就该这么建!

加我好友,拉你进群

求求了,数据库索引就该这么建!

原文始发于微信公众号(Java知音):求求了,数据库索引就该这么建!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/286948.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!