面试题答案
一键面试Seq Scan(顺序扫描)
- 作用:顺序扫描会对表中的每一行数据依次进行读取,从表的开头遍历到结尾,不依赖索引。它读取整个表的数据页,然后对每一行数据进行过滤,判断是否满足查询条件。
- 适用场景:
- 当表非常小,全表扫描的成本低于使用索引时。例如只有几十行数据的表,使用索引可能带来额外的索引查找开销,不如直接全表扫描。
- 查询条件没有合适的索引支持,例如在一个没有索引的列上进行过滤查询。如
SELECT * FROM users WHERE random_column = 'value';
,这里random_column
没有索引,就可能触发顺序扫描。 - 大部分数据都满足查询条件,全表扫描的效率可能比通过索引多次定位数据更高。例如查询
SELECT * FROM orders WHERE order_date > '2023 - 01 - 01';
,如果大部分订单日期都在这个时间之后,顺序扫描可能更优。
Index Scan(索引扫描)
- 作用:索引扫描利用索引结构来快速定位满足查询条件的数据行。索引是一种数据结构,它提供了一种快速查找数据的方式。通过索引,数据库可以快速定位到满足条件的索引项,然后通过索引项找到对应的数据行。
- 适用场景:
- 当查询条件在有索引的列上,并且索引的选择性较好(即索引列的值分布比较均匀,能有效减少扫描的数据量)。例如
SELECT * FROM products WHERE product_id = 123;
,如果product_id
列上有索引,就很可能触发索引扫描快速定位到对应产品。 - 范围查询时,如果索引是有序的,索引扫描可以快速定位到满足范围条件的起始位置,并按顺序读取满足条件的数据。如
SELECT * FROM employees WHERE salary > 50000;
,若salary
列有索引,可利用索引快速定位符合条件的数据。 - 当查询的列包含在索引中(覆盖索引),数据库可以直接从索引中获取所需数据,而无需回表操作(即从索引找到数据行对应的物理位置再去读取完整数据行),这样能大大提高查询效率。例如
SELECT product_name FROM products WHERE product_id = 123;
,如果product_id
和product_name
都在同一个索引中,就可以直接从索引获取数据。
- 当查询条件在有索引的列上,并且索引的选择性较好(即索引列的值分布比较均匀,能有效减少扫描的数据量)。例如
Nested Loop(嵌套循环)
- 作用:嵌套循环是一种连接(Join)操作的执行方式。它将两个表(内表和外表)进行连接,对外表的每一行数据,都在内表中进行匹配查找满足连接条件的行。具体过程是外层循环遍历外表的每一行,对于每一行,内层循环在内表中进行全表扫描或索引扫描(取决于内表是否有合适索引及其他因素)来寻找匹配的行,然后将匹配的行组合作为结果输出。
- 适用场景:
- 当外表数据量较小,内表有合适的索引时,嵌套循环连接效率较高。因为外层循环次数少,每次对内表进行索引扫描能快速找到匹配行。例如一个小的
departments
表和一个大的employees
表通过department_id
连接,departments
表数据量小作为外表,employees
表department_id
列有索引,此时嵌套循环连接可能是较好选择。 - 当连接条件比较复杂,其他连接方式(如哈希连接、合并连接)难以有效利用时,嵌套循环连接可能会被选择。因为嵌套循环连接可以灵活地处理各种连接条件,即使条件涉及多个列的复杂运算。
- 当外表数据量较小,内表有合适的索引时,嵌套循环连接效率较高。因为外层循环次数少,每次对内表进行索引扫描能快速找到匹配行。例如一个小的