1. 主键索引底层的实现原理
- 定义
主键索引是数据库中用于唯一标识表中每一行记录的索引,常见的底层实现是 B+ 树结构。B+ 树是一种平衡的多路搜索树,由内部节点和叶子节点组成。内部节点只存储索引键和指向下一层节点的指针,不存储实际数据;叶子节点存储索引键和对应的实际数据记录,并且所有叶子节点通过指针连接成一个有序链表。查询时从根节点开始,依据索引键的值在内部节点中比较,逐步向下查找直至找到对应的叶子节点获取数据。
- 要点
- 平衡性:B+ 树所有叶子节点在同一层,保证查询时间复杂度稳定在 O (log n),n 为数据记录数量。
- 多路搜索:每个节点可有多个子节点,降低树的高度,减少磁盘 I/O 次数,提升查询效率。
- 链表结构:叶子节点间通过指针连接成有序链表,便于进行范围查询。
- 应用
在电商系统的商品表中,以商品 ID 作为主键索引。当用户根据商品 ID 查询商品详情时,数据库能通过 B+ 树快速定位到对应的商品记录,提高查询效率。
SQL 代码示例
sql
-- 创建商品表并设置商品 ID 为主键索引
CREATE TABLE products (product_id INT PRIMARY KEY,product_name VARCHAR(100),price DECIMAL(10, 2)
);-- 插入数据
INSERT INTO products (product_id, product_name, price) VALUES (1, 'iPhone', 999.99);
INSERT INTO products (product_id, product_name, price) VALUES (2, 'iPad', 599.99);-- 根据主键索引查询商品
SELECT * FROM products WHERE product_id = 1;
Java 代码示例(模拟 B+ 树查询)
java
import java.util.ArrayList;
import java.util.List;// 简单模拟 B+ 树节点
class BPlusTreeNode {List<Integer> keys;List<BPlusTreeNode> children;boolean isLeaf;BPlusTreeNode next;public BPlusTreeNode(boolean isLeaf) {this.keys = new ArrayList<>();this.children = new ArrayList<>();this.isLeaf = isLeaf;this.next = null;}
}// 简单模拟 B+ 树查询
class BPlusTree {BPlusTreeNode root;public BPlusTree() {this.root = new BPlusTreeNode(true);}public Integer search(int key) {BPlusTreeNode node = root;while (!node.isLeaf) {int i = 0;while (i < node.keys.size() && key > node.keys.get(i)) {i++;}node = node.children.get(i);}for (int i = 0; i < node.keys.size(); i++) {if (node.keys.get(i) == key) {return key;}}return null;}
}public class BPlusTreeExample {public static void main(String[] args) {BPlusTree bPlusTree = new BPlusTree();Integer result = bPlusTree.search(5);System.out.println(result);}
}
2. 01 索引
- 定义
“01 索引” 指的是位图索引,它是一种特殊的索引结构,用位图表示每个索引键的值。对于每个索引键,位图中的每一位对应一个数据记录,若该记录的索引键值等于该索引键,对应位为 1,否则为 0。通过位图的位运算可快速进行查询和过滤。
- 要点
- 空间效率高:对于低基数(不同值数量较少)的列,能显著减少存储空间。
- 查询效率高:利用位运算可快速查询和过滤,尤其适用于多条件查询。
- 更新成本高:数据记录插入、更新或删除时,需更新对应位图,成本较高。
- 应用
在数据仓库的用户表中,对于性别(只有男、女两种值)列可使用位图索引。当需要统计男性用户数量时,通过位图的位运算能快速得出结果。
SQL 代码示例(创建位图索引)
sql
-- 假设表名为 users,列名为 gender
CREATE TABLE users (user_id INT,gender CHAR(1)
);-- 创建位图索引
CREATE BITMAP INDEX idx_users_gender ON users (gender);-- 插入数据
INSERT INTO users (user_id, gender) VALUES (1, 'M');
INSERT INTO users (user_id, gender) VALUES (2, 'F');-- 查询男性用户
SELECT * FROM users WHERE gender = 'M';
3. 如何在长文本中快捷的筛选出你的名字
- 定义
在长文本中筛选指定名字可借助字符串匹配算法。常见算法有朴素匹配算法、KMP 算法、Boyer - Moore 算法等,这些算法通过不同策略在长文本中查找目标名字的位置。
- 要点
- 朴素匹配算法:简单直观,但时间复杂度高,为 O (m * n),m 是长文本长度,n 是要匹配名字的长度。
- KMP 算法:预处理要匹配的名字,构建部分匹配表,避免匹配过程中的不必要回溯,时间复杂度为 O (m + n)。
- Boyer - Moore 算法:从右向左匹配,利用坏字符规则和好后缀规则跳过尽可能多的字符,平均时间复杂度接近 O (m)。
- 应用
在新闻文章的搜索系统中,用户输入关键词(如人名),系统可使用高效的字符串匹配算法在大量文章中快速筛选出包含该关键词的文章。
Java 代码示例(使用 KMP 算法)
java
public class KMP {public static int kmpSearch(String text, String pattern) {int[] lps = computeLPSArray(pattern);int i = 0; // 文本指针int j = 0; // 模式指针while (i < text.length()) {if (pattern.charAt(j) == text.charAt(i)) {j++;i++;}if (j == pattern.length()) {return i - j; // 找到匹配} else if (i < text.length() && pattern.charAt(j) != text.charAt(i)) {if (j != 0) {j = lps[j - 1];} else {i++;}}}return -1; // 未找到匹配}private static int[] computeLPSArray(String pattern) {int[] lps = new int[pattern.length()];int len = 0;int i = 1;lps[0] = 0;while (i < pattern.length()) {if (pattern.charAt(i) == pattern.charAt(len)) {len++;lps[i] = len;i++;} else {if (len != 0) {len = lps[len - 1];} else {lps[i] = 0;i++;}}}return lps;}public static void main(String[] args) {String text = "Hello, my name is John. John is a good person.";String pattern = "John";int index = kmpSearch(text, pattern);System.out.println("Index of pattern: " + index);}
}
4. 数据库的完整性约束, 事务隔离级别
- 数据库的完整性约束
- 定义
数据库的完整性约束是为保证数据库中数据的正确性、一致性和有效性而设置的规则。包括实体完整性、参照完整性和用户定义的完整性。实体完整性确保表中每一行记录唯一,通常通过主键约束实现;参照完整性保证表之间关联关系正确,通常通过外键约束实现;用户定义的完整性是根据业务需求定义的规则,如检查约束、默认值约束等。
- 要点
- 主键约束:一个表只能有一个主键,主键值必须唯一且不为空。
- 外键约束:外键是表中的列,引用另一个表的主键,其值必须存在于被引用表的主键中或为空。
- 检查约束:限制列的取值范围,如年龄必须大于 0。
- 默认值约束:为列指定默认值,插入记录时若未指定该列值,则使用默认值。
- 应用
在学生选课系统中,学生表的学生 ID 作为主键,课程表的课程 ID 作为主键。选课表中通过外键关联学生 ID 和课程 ID,确保选课信息的正确性。同时,可设置成绩列的检查约束,保证成绩在 0 - 100 分之间。
SQL 代码示例(创建完整性约束)
sql
-- 创建学生表
CREATE TABLE students (student_id INT PRIMARY KEY,name VARCHAR(50) NOT NULL,age INT CHECK (age > 0)
);-- 创建课程表
CREATE TABLE courses (course_id INT PRIMARY KEY,course_name VARCHAR(100)
);-- 创建选课表
CREATE TABLE enrollments (enrollment_id INT PRIMARY KEY,student_id INT,course_id INT,grade DECIMAL(5, 2) CHECK (grade >= 0 AND grade <= 100),FOREIGN KEY (student_id) REFERENCES students(student_id),FOREIGN KEY (course_id) REFERENCES courses(course_id)
);
事务隔离级别
- 定义
事务隔离级别用于控制多个事务之间的可见性和并发操作行为。不同隔离级别影响事务的并发性能和数据一致性。常见的事务隔离级别有读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)。
- 要点
- 读未提交:一个事务可读取另一个未提交事务的数据,可能出现脏读、不可重复读和幻读问题。
- 读已提交:一个事务只能读取另一个已提交事务的数据,避免脏读问题,但可能出现不可重复读和幻读问题。
- 可重复读:在一个事务中,多次读取同一数据结果相同,避免脏读和不可重复读问题,但可能出现幻读问题。
- 串行化:所有事务依次执行,避免脏读、不可重复读和幻读问题,但并发性能最低。
- 应用
在银行转账系统中,为保证数据一致性,可将事务隔离级别设置为可重复读。例如,在一个事务中进行转账操作时,多次读取账户余额结果相同,避免出现数据不一致的情况。
SQL 代码示例(设置事务隔离级别)
sql
-- 设置事务隔离级别为可重复读
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;-- 开始事务
START TRANSACTION;-- 执行转账操作
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;-- 提交事务
COMMIT;
5. 数据库悲观锁怎么实现的
- 定义
数据库悲观锁是一种保守的并发控制策略,假设数据处理过程中会发生冲突,因此在访问数据前先对数据加锁,防止其他事务修改数据。常见实现方式有共享锁(读锁)和排他锁(写锁)。
- 要点
- 共享锁:多个事务可同时对同一数据加共享锁用于读取数据。加共享锁后,其他事务可继续加共享锁,但不能加排他锁,直到所有共享锁释放。
- 排他锁:一个事务对数据加排他锁后,其他事务不能再对该数据加任何类型的锁,直到排他锁释放。排他锁用于修改数据,保证数据一致性。
- 应用
在电商系统的库存管理中,当用户下单时,对相应商品的库存记录加排他锁,防止其他用户同时购买导致库存数据不一致。
SQL 代码示例(使用排他锁)
sql
-- 会话 1
START TRANSACTION;
SELECT * FROM products WHERE product_id = 1 FOR UPDATE;
-- 进行库存更新操作
UPDATE products SET stock = stock - 1 WHERE product_id = 1;
COMMIT;-- 会话 2
START TRANSACTION;
SELECT * FROM products WHERE product_id = 1 FOR UPDATE;
-- 会被阻塞,直到会话 1 的排他锁释放
COMMIT;
6. 建表的原则
- 定义
建表原则是为保证数据库设计合理、高效、可维护和可扩展而遵循的准则。设计表结构时需考虑数据的完整性、一致性、性能和可维护性等因素。
- 要点
- 遵循范式:尽量遵循数据库的范式设计,如第一范式(1NF)、第二范式(2NF)和第三范式(3NF),减少数据冗余。
- 选择合适的数据类型:根据数据特点和使用场景,选择合适的数据类型,避免数据类型不匹配导致的性能问题。
- 合理设置主键和索引:为表设置合适的主键,确保数据唯一性。根据查询需求,合理创建索引,提高查询性能。
- 考虑数据的扩展性:设计表结构时要考虑未来数据增长和业务变化,预留一定扩展性。
- 应用
在企业的员工管理系统中,设计员工表、部门表和项目表时,遵循建表原则。员工表以员工 ID 为主键,部门表以部门 ID 为主键,项目表以项目 ID 为主键。通过外键关联员工和部门、员工和项目,同时根据查询需求在相关列上创建索引。
SQL 代码示例(创建符合建表原则的表)
sql
-- 创建部门表
CREATE TABLE departments (department_id INT PRIMARY KEY,department_name VARCHAR(100)
);-- 创建员工表
CREATE TABLE employees (employee_id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL,department_id INT,salary DECIMAL(10, 2),hire_date DATE,FOREIGN KEY (department_id) REFERENCES departments(department_id),INDEX idx_department_id (department_id)
);-- 创建项目表
CREATE TABLE projects (project_id INT PRIMARY KEY,project_name VARCHAR(100),start_date DATE,end_date DATE
);-- 创建员工项目关联表
CREATE TABLE employee_projects (employee_project_id INT PRIMARY KEY AUTO_INCREMENT,employee_id INT,project_id INT,FOREIGN KEY (employee_id) REFERENCES employees(employee_id),FOREIGN KEY (project_id) REFERENCES projects(project_id)
);
7. 索引的定义和用法
- 定义
索引是数据库中一种特殊的数据结构,用于加快数据查询速度。它对表中某些列的值进行排序和存储,建立快速查找的映射关系,使数据库查询时可直接定位所需数据记录,无需扫描整个表。
- 用法
- 创建索引:使用
CREATE INDEX
语句创建索引,如CREATE INDEX idx_column_name ON table_name (column_name);
- 使用索引:在查询语句中,数据库会自动根据索引进行优化,提高查询效率,如
SELECT * FROM table_name WHERE column_name = 'value';
- 删除索引:使用
DROP INDEX
语句删除索引,如DROP INDEX idx_column_name ON table_name;
- 要点
- 选择合适的列创建索引:通常在经常用于查询条件、排序和连接的列上创建索引。
- 避免创建过多的索引:过多索引会增加数据插入、更新和删除的开销,同时占用更多存储空间。
- 定期维护索引:随着数据变化,索引可能碎片化,影响查询性能,需定期重建和优化索引。
- 应用
在电商系统的商品搜索功能中,对商品名称、价格等列创建索引。当用户根据商品名称或价格范围进行搜索时,数据库可利用索引快速定位到相关商品记录。
SQL 代码示例(创建和使用索引)
sql
-- 创建商品表
CREATE TABLE products (product_id INT PRIMARY KEY,product_name VARCHAR(100),price DECIMAL(10, 2),category VARCHAR(50)
);-- 创建索引
CREATE INDEX idx_product_name ON products (product_name);
CREATE INDEX idx_price ON products (price);-- 使用索引进行查询
SELECT * FROM products WHERE product_name = 'iPhone';
SELECT * FROM products WHERE price > 500;-- 删除索引
DROP INDEX idx_product_name ON products;
8. 怎么创建表
- 定义
创建表是数据库操作的基本操作,通过 SQL 语句在数据库中创建新表。创建时需指定表名、列名、数据类型和约束条件等信息。
- 要点
- 表名:应具有描述性,清晰表达表的用途。
- 列名:也应具有描述性,清晰表达列的含义。
- 数据类型:根据数据特点和使用场景,选择合适的数据类型,如整数类型、字符串类型、日期类型等。
- 约束条件:可为列添加约束条件,如主键约束、外键约束、唯一约束、检查约束等,保证数据的完整性和一致性。
- 应用
在开发一个博客系统时,需要创建文章表、用户表和评论表。通过合理创建表结构,保证系统数据的有效存储和管理。
SQL 代码示例(创建表)
sql
-- 创建用户表
CREATE TABLE users (user_id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) UNIQUE NOT NULL,password VARCHAR(100) NOT NULL,email VARCHAR(100) UNIQUE,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);-- 创建文章表
CREATE TABLE articles (article_id INT PRIMARY KEY AUTO_INCREMENT,title VARCHAR(200) NOT NULL,content TEXT,author_id INT,published_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,FOREIGN KEY (author_id) REFERENCES users(user_id)
);-- 创建评论表
CREATE TABLE comments (comment_id INT PRIMARY KEY AUTO_INCREMENT,article_id INT,user_id INT,comment_text TEXT,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,FOREIGN KEY (article_id) REFERENCES articles(article_id),FOREIGN KEY (user_id) REFERENCES users(user_id)
);
9. 已知两条 SQL 语句, 如何根据这两条语句建索引
- 定义
根据 SQL 语句创建索引是为提高查询性能。需要分析 SQL 语句中的查询条件、排序条件和连接条件,在这些条件涉及的列上创建索引。
- 要点
- 查询条件:在经常用于
WHERE
子句的列上创建索引,如WHERE column_name = 'value'
。 - 排序条件:在经常用于
ORDER BY
子句的列上创建索引,如ORDER BY column_name
。 - 连接条件:在经常用于
JOIN
子句的列上创建索引,如JOIN table_name ON table1.column_name = table2.column_name
。
- 应用
在一个图书管理系统中,有两条 SQL 语句:一条用于查询某一分类下价格大于 50 元的图书,另一条用于按图书出版日期排序查询。可根据这两条语句在分类列、价格列和出版日期列上创建索引。
SQL 代码示例(根据 SQL 语句创建索引)
sql
-- 假设有两条 SQL 语句
-- 语句 1: SELECT * FROM books WHERE category = 'fiction' AND price > 50;
-- 语句 2: SELECT * FROM books ORDER BY publish_date;-- 创建图书表
CREATE TABLE books (book_id INT PRIMARY KEY,title VARCHAR(200),category VARCHAR(50),price DECIMAL(10, 2),publish_date DATE
);-- 根据语句 1 创建复合索引
CREATE INDEX idx_category_price ON books (category, price);-- 根据语句 2 创建索引
CREATE INDEX idx_publish_date ON books (publish_date);
10. select 语句实现顺序
- 定义
SELECT
语句的执行顺序并非按照语句中各子句的书写顺序,而是遵循特定的逻辑顺序。数据库先确定查询范围和条件,再进行数据筛选、分组、排序等操作,最后返回结果。
- 要点
SELECT
语句的执行顺序如下:
- FROM:指定要查询的表或视图。
- JOIN:若有连接操作,进行表的连接。
- WHERE:根据条件筛选记录。
- GROUP BY:对筛选后的记录进行分组。
- HAVING:对分组后的结果进行筛选。
- SELECT:选择要返回的列。
- DISTINCT:去除重复的记录。
- ORDER BY:对结果进行排序。
- LIMIT:限制返回的记录数量。
- 应用
在学生成绩统计系统中,要统计每个班级的平均成绩,并筛选出平均成绩大于 80 分的班级,按平均成绩降序排列,取前 5 个班级。通过了解 SELECT
语句的执行顺序,可正确编写查询语句。
SQL 代码示例(演示 SELECT
语句执行顺序)
sql
-- 假设有两个表:students 和 scores
-- students 表包含 student_id, class_id, name 列
-- scores 表包含 score_id, student_id, score 列SELECT s.class_id, AVG(sc.score) AS average_score
FROM students s
JOIN scores sc ON s.student_id = sc.student_id
WHERE sc.score > 60
GROUP BY s.class_id
HAVING AVG(sc.score) > 80
ORDER BY average_score DESC
LIMIT 5;
在这个示例中,数据库先执行 FROM
和 JOIN
操作,连接 students
表和 scores
表;接着执行 WHERE
子句,筛选出成绩大于 60 分的记录;然后执行 GROUP BY
操作,按班级 ID 分组;再执行 HAVING
子句,筛选出平均成绩大于 80 分的班级;之后执行 SELECT
操作,选择班级 ID 和平均成绩;最后执行 ORDER BY
和 LIMIT
操作,对结果排序并限制返回的记录数量。
友情提示:本文已经整理成文档,可以到如下链接免积分下载阅读
https://download.csdn.net/download/ylfhpy/90567261