今天在看面经的时候看到联合索引和聚合索引的时候感觉自己不是很明确,于是查阅了大量的资料,终于弄明白了,写一篇文章来做一个总结
1.联合索引
什么是联合索引?
联合所以就是我们将数据表中的多个字段联合起来作为一个索引。(可能有点答非所问)下面我就来说一下我自己的理解。
首先我们建立一个联合索引之后就相当于创建了一颗B+树。联合索引在使用的时候最重要的是遵循最左匹配原则,通俗点讲就是让数据库中区分度高的字段优先放在联合索引的最左边。举个例子,我们建立了一个索引(a,b,c)相当于我们建立了(a),(b,c),(a,b,c)这些索引,但是其实这三个索引在实际的数据库中是没有索引的。这点一定要注意。
下面来讲一些题目来说明一下我们的联合索引。
1.如果sql为
SELECT * FROM table WHERE a = 1 and b = 2 and c = 3;
那么我们应该如何去建立联合索引呢?
可能有人会说我们建立的联合索引是(a,b,c),这么说虽然也没错,但是如果你在面试的时候这么说的话,显得你水平比较低,思考不高全面。其实这个问题没有固定的联合索引,(a,b,c),(c,b,a),(b,a,c)都是可以的,那么我们应该怎么和面试官说呢。我们应该这样说:
首先我们应该先判断a,b,c三个字段的对于数据的区分度,将区分度进行排序,比如区分度按照从大到小的顺序为c,b,a那么我们可以建立索引(c,b,a),可能有同学问了,不是遵循最左匹配原则吗,那我们的sql中c应该在最前面啊,这个其实和我们的sql的优化器有关,优化器会自动根据我们建立的联合索引来调整sql中a,b,c的顺序,所以谁在前无所谓,但是我们自己在写的时候还是要按照c,b,a的顺序写的。
2.sql为
SELECT * FROM table WHERE a > 1 and b = 2;
如何建立联合索引?
如果有同学回答说建立(a,b)这个索引的话,那么就是错误的,为什么呢?首先要补充一点重要的知识:联合索引中如果遇到了范围查找,后面的索引就会失效。所以如果我们建立了(a,b)这样的索引的话,a可以用上索引,但是b用不到索引。 我们应该建立(b,a)的索引,这样b和a都可以用到索引了。
3.sql为
SELECT * FROM `table` WHERE a > 1 and b = 2 and c > 3;
应该如何建立索引?
这种情况建立的索引也是不唯一的,和第一题类似,要具体分析区分度的大小,可以建立(b,a)也可以建立(b,c)
通过上面的例子,希望大家能有所连接什么是联合索引以及如何建立联合索引。因为我现在一边找工作一边写博客,可能说的不是很详细,等俺offer到手回来详细补充的。
2,覆盖索引
什么是覆盖索引?
覆盖索引(Covering Index)是一种优化数据库查询的技术,它可以显著地提高查询性能。覆盖索引利用了数据库引擎的内部机制,在查询时不需要直接访问数据表,而是只需访问索引即可返回查询结果,从而避免了访问磁盘上的数据表,减少了磁盘 I/O 操作,提高了查询速度。
覆盖索引的原理是在创建索引时,除了保存索引的键值,还保存了其他查询语句所需要的列值。当数据库执行查询时,只需要在索引中搜索符合条件的记录,然后直接从索引中获取所需的列值,而不必去访问数据表。因为索引通常比数据表小得多,所以在内存中查询速度更快,从而提高了查询性能。
覆盖索引适用场景
1. 查询语句只需要返回索引列和覆盖列的值,不需要查询其他列的值。
2。 数据表的行数较大,而索引列的值域较小,覆盖列的值也不会过于庞大,因此使用覆盖索引可以减少磁盘 I/O 操作,提高查询效率。
3. 覆盖列的数据类型不应过大,以避免索引的大小过大。
需要注意的是,覆盖索引虽然可以提高查询性能,但也有一些副作用,例如索引的更新和维护需要更多的资源和时间。此外,对于一些特定的查询语句,覆盖索引可能会带来负面影响,因此需要进行适当的优化和测试。
如何建立覆盖索引
假设有一个名为 orders 的数据表,其中包含以下列:order_id、customer_id、order_date 和 total_amount。现在需要查询某个特定顾客的所有订单,按照订单日期排序,同时返回订单号和订单总金额。可以使用如下 SQL 查询语句:
SELECT order_id, total_amount FROM orders WHERE customer_id = 123 ORDER BY order_date;
为了优化查询性能,可以创建一个覆盖索引来包含 customer_id、order_date 和 total_amount 列,以便在查询时避免访问数据表。可以使用以下 SQL 命令创建覆盖索引:
CREATE INDEX idx_orders_customer ON orders (customer_id, order_date) INCLUDE (order_id, total_amount);
上述命令创建了一个名为 idx_orders_customer 的索引,包含 customer_id 和 order_date 列,并包括 order_id 和 total_amount 列作为覆盖列。现在,当执行查询语句时,数据库引擎会尝试使用该覆盖索引来返回查询结果,而不需要访问数据表,从而提高查询性能。