当前位置: 首页 > news >正文

第七章 数据库编程

1 数据库编程基础

1.1 数据库系统概述

      数据库系统是由数据库、数据库管理系统(DBMS)和应用程序组成的完整系统。其主要目的是高效地存储、管理和检索数据。现代数据库系统通常分为以下几类:

  • 关系型数据库(RDBMS):如MySQL、PostgreSQL、Oracle等,使用表格结构存储数据
  • NoSQL数据库:如MongoDB、Cassandra、Redis等,适用于非结构化或半结构化数据
  • NewSQL数据库:如CockroachDB、TiDB等,结合了关系型和NoSQL的优点
  • 内存数据库:如Redis、Memcached等,数据主要存储在内存中

1.2 关系型数据库基础架构

        以MySQL 8.0为例,该架构清晰地呈现了从客户端发送SQL语句到数据存储的完整处理流程,其核心组件及功能如下:

  1. 连接器(Connector):负责客户端与MySQL服务器之间的通信协议,建立和管理连接,处理用户认证和权限验证。
  2. 查询缓存(Query Cache):用于缓存SQL语句的执行结果。当收到查询请求时,MySQL会首先检查查询缓存,若存在匹配的缓存结果,则直接返回,避免重复执行查询,提高响应速度。
  3. 解析器(Parser):包含词法分析和语法分析。词法分析将SQL语句分解为一个个标记(token),语法分析则根据SQL语法规则,将标记组合成语法树,以便后续处理。
  4. 执行器(Executor):负责执行SQL语句的查询流程。它包括执行计划生成、优化器(Optimizer)和预处理器(Preprocessor)。执行计划确定如何高效地执行查询,优化器对执行计划进行优化,预处理器则处理一些准备工作,如检查表是否存在、权限验证等。最终,执行器调用API接口与存储引擎交互,执行数据操作。
  5. 存储引擎(Storage Engine):如InnoDB、MyISAM等,负责数据的实际存储和检索。不同的存储引擎提供不同的功能,例如InnoDB支持事务处理和外键约束,而MyISAM则提供更高的读取性能。

       MySQL数据库架构的设计使其能够高效地处理客户端请求,并通过查询缓存和优化器提高查询性能。同时,支持多种存储引擎,使其能够适应不同的应用场景和数据存储需求。

1.3 数据库连接技术

1.3.1 Java连接MySQL

         目前已经很少有下方举例的这种写法了,很多框架都做了封装,只需yaml文件对连接的数据库进行配置。

// Java中使用JDBC连接MySQL的示例
import java.sql.*;public class MySQLDemo {// MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URLstatic final String JDBC_DRIVER = "com.mysql.jdbc.Driver";  static final String DB_URL = "jdbc:mysql://localhost:3306/RUNOOB";// MySQL 8.0 以上版本 - JDBC 驱动名及数据库 URL//static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";  //static final String DB_URL = "jdbc:mysql://localhost:3306/RUNOOB?        useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";// 数据库的用户名与密码,需要根据自己的设置static final String USER = "root";static final String PASS = "123456";public static void main(String[] args) {Connection conn = null;Statement stmt = null;try{// 注册 JDBC 驱动Class.forName(JDBC_DRIVER);// 打开链接System.out.println("连接数据库...");conn = DriverManager.getConnection(DB_URL,USER,PASS);// 执行查询System.out.println(" 实例化Statement对象...");stmt = conn.createStatement();String sql;sql = "SELECT id, name, url FROM websites";ResultSet rs = stmt.executeQuery(sql);// 展开结果集数据库while(rs.next()){// 通过字段检索int id  = rs.getInt("id");String name = rs.getString("name");String url = rs.getString("url");// 输出数据System.out.print("ID: " + id);System.out.print(", 站点名称: " + name);System.out.print(", 站点 URL: " + url);System.out.print("\n");}// 完成后关闭rs.close();stmt.close();conn.close();}catch(SQLException se){// 处理 JDBC 错误se.printStackTrace();}catch(Exception e){// 处理 Class.forName 错误e.printStackTrace();}finally{// 关闭资源try{if(stmt!=null) stmt.close();}catch(SQLException se2){}// 什么都不做try{if(conn!=null) conn.close();}catch(SQLException se){se.printStackTrace();}}System.out.println("Goodbye!");}
}

1.3.2 Python连接MySQL

#1 使用pymysql模块import pymysql## 建立数据库连接
try:conn = pymysql.connect(host='localhost',  # 数据库主机地址,本地数据库一般为 'localhost'user='root',  # 数据库用户名password='your_password',  # 数据库密码,替换为你自己设置的密码database='test_db',  # 要连接的数据库名,如果不存在需要先创建charset='utf8mb4'  # 字符编码)print("数据库连接成功!")
except pymysql.Error as e:print(f"数据库连接失败:{e}")
finally:if conn:conn.close()#2 使用MySQL Connector模块import mysql.connector# 连接到数据库
conn = mysql.connector.connect(host='localhost',user='root',password='password',database='mydatabase'
)# 创建游标对象
cursor = conn.cursor()# 执行SQL查询
cursor.execute("SELECT * FROM mytable")# 获取查询结果
result = cursor.fetchall()# 打印查询结果
for row in result:print(row)# 关闭游标和连接
cursor.close()
conn.close()

1.4 SQL基础

        结构化查询语言(SQL)是与关系型数据库交互的标准语言。以下是SQL的核心命令分类:

1.4.1 数据定义语言(DDL)

-- 创建表
CREATE TABLE employees (id INT PRIMARY KEY,name VARCHAR(100) NOT NULL,department VARCHAR(50),salary DECIMAL(10,2),hire_date DATE
);-- 修改表结构
ALTER TABLE employees ADD COLUMN email VARCHAR(100);-- 删除表
DROP TABLE employees;

1.4.2 数据操作语言(DML)

-- 插入数据
INSERT INTO employees (id, name, department, salary, hire_date)
VALUES (1, 'John Doe', 'Engineering', 75000.00, '2020-01-15');-- 更新数据
UPDATE employees SET salary = 80000.00 WHERE id = 1;-- 删除数据
DELETE FROM employees WHERE id = 1;

1.4.3 数据查询语言(DQL)

-- 基本查询
SELECT * FROM employees;-- 条件查询
SELECT name, salary FROM employees WHERE department = 'Engineering' AND salary > 70000;-- 排序
SELECT * FROM employees ORDER BY salary DESC;-- 分组和聚合
SELECT department, AVG(salary) as avg_salary 
FROM employees 
GROUP BY department 
HAVING AVG(salary) > 60000;

1.4.4 数据控制语言(DCL)

-- 授予权限
GRANT SELECT, INSERT ON employees TO user1;-- 撤销权限
REVOKE INSERT ON employees FROM user1;

2 编程技术精要

2.1 事务处理与ACID保障

# 金融交易场景实现START TRANSACTION;
-- 账户A扣款
UPDATE accounts SET balance = balance - 1000 WHERE account_id = 'A123';
-- 账户B收款
UPDATE accounts SET balance = balance + 1000 WHERE account_id = 'B456';
-- 检查账户状态
SELECT @row_count = ROW_COUNT();
IF @row_count < 2 THENROLLBACK;SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Transfer failed: account not found';
ELSECOMMIT;
END IF;

2.2 存储过程

2.2.1 PL/SQL块结构

        PL/SQL(Procedural Language extensions to SQL)是Oracle数据库的过程化编程语言,其基本单位是"块"(Block)。一个完整的PL/SQL块由以下三部分组成:

# PL/SQL块的基本结构[DECLARE]-- 声明部分(可选):定义变量、常量、游标等
BEGIN-- 执行部分(必需):包含PL/SQL语句和SQL语句
[EXCEPTION]-- 异常处理部分(可选):处理运行时错误
END;

示例:

DECLAREv_emp_name VARCHAR2(100);v_salary NUMBER;
BEGINSELECT employee_name, salary INTO v_emp_name, v_salaryFROM employeesWHERE employee_id = 100;DBMS_OUTPUT.PUT_LINE('Employee: ' || v_emp_name || ', Salary: ' || v_salary);
EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('Employee not found');
END;

2.2.2 变量和常量的定义

1. 变量定义规范

  • 语法:变量名 [CONSTANT] 数据类型 [NOT NULL] [:= 初始值]
  • 关键特性:
    • 作用域从声明处到块结束
    • 支持%TYPE属性引用表结构(如v_salary employees.salary%TYPE
    • 复合类型:记录(RECORD)、表(TABLE)、嵌套表(VARRAY)
DECLAREv_count NUMBER := 0;  -- 数字变量并初始化v_name VARCHAR2(50);  -- 字符串变量v_hiredate DATE := SYSDATE;  -- 日期变量v_valid BOOLEAN DEFAULT TRUE;  -- 布尔变量
BEGIN-- 使用变量
END;

2. 常量定义要点

  • 必须初始化且值不可变
  • 示例:c_commission_pct CONSTANT NUMBER(3,2) := 0.15;
DECLAREc_pi CONSTANT NUMBER := 3.14159;c_tax_rate CONSTANT NUMBER(5,2) := 0.08;
BEGIN-- 使用常量
END;

2.2.3 控制结构

1. 条件控制

  •         IF-THEN-ELSIF:多分支判断
#语法:IF condition1 THENstatements1;
ELSIF condition2 THENstatements2;
ELSEstatements3;
END IF;#示例:
DECLAREv_score NUMBER := 85;
BEGINIF v_score >= 90 THENDBMS_OUTPUT.PUT_LINE('优秀');ELSIF v_score >= 80 THENDBMS_OUTPUT.PUT_LINE('良好');ELSEDBMS_OUTPUT.PUT_LINE('一般');END IF;
END;
  • CASE表达式:模式匹配
#语法:
CASE selectorWHEN value1 THEN statements1;WHEN value2 THEN statements2;...ELSE else_statements;
END CASE;#示例:
CASE WHEN v_grade = 'A' THEN v_bonus := 5000;WHEN v_grade = 'B' THEN v_bonus := 3000;ELSE v_bonus := 1000;
END CASE;

2. 循环控制

  • 基本LOOP
#语法:LOOPstatements;EXIT [WHEN condition];
END LOOP;
  • WHILE-LOOP
#语法:
WHILE condition LOOPstatements;
END LOOP;
  • FOR-LOOP
#语法:
FOR counter IN [REVERSE] start_value..end_value LOOPstatements;
END LOOP;
  • 示例:
BEGIN-- 基本LOOPDECLAREv_counter NUMBER := 1;BEGINLOOPDBMS_OUTPUT.PUT_LINE('Counter: ' || v_counter);v_counter := v_counter + 1;EXIT WHEN v_counter > 5;END LOOP;END;-- FOR循环FOR i IN 1..5 LOOPDBMS_OUTPUT.PUT_LINE('Index: ' || i);END LOOP;-- WHILE循环DECLAREj NUMBER := 1;BEGINWHILE j <= 5 LOOPDBMS_OUTPUT.PUT_LINE('While index: ' || j);j := j + 1;END LOOP;END;
END;

2.2.4 存储过程

存储过程是存储在数据库中的命名PL/SQL块,可以被多次调用。

1. 创建存储过程

#语法:CREATE [OR REPLACE] PROCEDURE procedure_name (param1 IN  NUMBER,param2 OUT VARCHAR2,param3 IN OUT DATE
)
IS-- 局部变量声明
BEGIN-- 执行逻辑
EXCEPTION-- 异常处理
END procedure_name;

参数模式:

  • IN:输入参数(默认)
  • OUT:输出参数
  • IN OUT:既可输入也可输出

示例:

CREATE OR REPLACE PROCEDURE update_salary (p_emp_id IN employees.employee_id%TYPE,p_percent IN NUMBER,p_status OUT VARCHAR2
) ASv_current_salary employees.salary%TYPE;v_new_salary employees.salary%TYPE;
BEGIN-- 获取当前工资SELECT salary INTO v_current_salaryFROM employeesWHERE employee_id = p_emp_id;-- 计算新工资v_new_salary := v_current_salary * (1 + p_percent/100);-- 更新工资UPDATE employeesSET salary = v_new_salaryWHERE employee_id = p_emp_id;p_status := 'SUCCESS: Salary updated from ' || v_current_salary || ' to ' || v_new_salary;COMMIT;
EXCEPTIONWHEN NO_DATA_FOUND THENp_status := 'ERROR: Employee not found';WHEN OTHERS THENp_status := 'ERROR: ' || SQLERRM;ROLLBACK;
END update_salary;

2. 调用存储过程

#示例:DECLAREv_status VARCHAR2(200);
BEGINupdate_salary(p_emp_id => 100, p_percent => 10, p_status => v_status);DBMS_OUTPUT.PUT_LINE(v_status);
END;# 或者使用EXEC命令: EXEC update_salary(100, 10, :status);
PRINT status;

2.2.5 实战案例

#以电商订单处理为例,优化后的存储过程实现DELIMITER //
CREATE PROCEDURE process_order(IN order_id BIGINT,OUT result_code INT
)
BEGINDECLARE EXIT HANDLER FOR SQLEXCEPTIONBEGINROLLBACK;SET result_code = -1;END;START TRANSACTION;-- 库存校验优化SELECT IF(i.available_stock >= oi.quantity, 1, 0) INTO @stock_okFROM inventory iINNER JOIN order_items oi USING(product_id)WHERE oi.order_id = order_idFOR UPDATE SKIP LOCKED;IF @stock_ok THEN-- 批量更新优化UPDATE inventory JOIN (SELECT product_id, SUM(quantity) AS total FROM order_items WHERE order_id = order_idGROUP BY product_id) AS t USING(product_id)SET available_stock = available_stock - t.total;UPDATE orders SET status = 'PROCESSING',update_time = NOW(6)WHERE order_id = order_id;ELSESIGNAL SQLSTATE '45000'SET MESSAGE_TEXT = 'Insufficient stock';END IF;COMMIT;SET result_code = 0;
END //
DELIMITER ;

优化关键点:

  • 使用SKIP LOCKED避免行锁竞争
  • 批量更新减少事务日志量
  • 精确的锁粒度控制
  • 显式事务边界定义

2.3 ODBC编程

2.3.1 数据库互联概述

1. 数据库互联的必要性
        在现代应用开发中,程序经常需要访问多种不同的数据库系统。由于各数据库厂商提供的接口各不相同,直接使用原生API会导致:

  • 应用程序与特定数据库绑定,移植性差
  • 开发人员需要学习多种数据库接口
  • 维护成本高,代码复用率低

2. 主流数据库互联技术

  • ODBC (Open Database Connectivity)
  1. 微软主导的开放标准
  2. 跨平台、跨数据库的通用接口
  3. Windows平台支持最佳
  • JDBC (Java Database Connectivity)
  1. Java语言的数据库连接标准
  2. 平台无关性
  3. 主要用于Java应用
  • ADO.NET
  1. .NET框架的数据访问组件
  2. 支持多种数据源
  3. 提供断开式数据访问
  • 原生API
  1. 各数据库厂商提供的专用接口
  2. 如Oracle的OCI、MySQL的C API等
  3. 性能最优但缺乏通用性

2.3.2 ODBC工作原理

1.  ODBC体系结构

ODBC应用系统的体系结构
 

ODBC采用分层架构,包含四个主要组件:  应用程序、驱动程序管理器(Driver Manager)、数据库驱动程序(Driver)、数据源。

2. 各组件功能

  • 应用程序
  1. 调用ODBC API函数
  2. 提交SQL语句
  3. 处理结果集
  • 驱动程序管理器
  1. 加载/卸载驱动程序
  2. 处理ODBC函数调用
  3. 参数验证和转发
  • 数据库驱动程序
  1. 连接特定数据库
  2. 将SQL转换为数据库原生命令
  3. 返回执行结果
  • 数据源
  1. 实际的数据库系统
  2. 如Oracle、SQL Server、MySQL等

2.3.3 ODBC API概述

       ODBC是一种使用SQL的程序设计接口。使用ODBC让应用程序的编写者避免了与数据源相联的复杂性。这项技术目前已经得到了大多数DBMS厂商们的广泛支持。ODBC是一种使用SQL 的程序设计接口。使用ODBC让应用程序的编写者避免了与数据源相联的复杂性。这项技术目前已经得到了大多数DBMS厂商们的广泛支持。
       Microsoft Developer Studio为大多数标准的数据库格式提供了32位ODBC驱动器。这些标准数据格式包括有:SQL Server,Access,Paradox,dBase,FoxPro,Excel,Oracle以及Microsoft Text。如果用户希望使用其他数据格式,用户需要相应的ODBC驱动器及DBMS。
        ODBC API是一个内容丰富的数据库编程接口,包括60多个函数、SQL数据类型以及常量的声明。ODBC API 是独立于DBMS和操作系统的,而且它与编程语言无关。ODBCAPI 以X/Open和ISO/IEC中的CLI规范为基础,ODBC 3.0完全实现了这两种规范,并添加了基于视图的数据库应用程序开发人员所需要的共同特性,例如可滚动光标。ODBC API中的函数由特定DBMS驱动程序的开发人员实现,应用程序用这些驱动程序调用函数,以独立于DBMS的方式访问数据。

        ODBC API涉及了数据源连接与管理、结果集检索、数据库管理、数据绑定、事务操作等内容。

  • ODBCAPI编程步骤

通常使用ODBCAPI开发数据库应用程序需要经过如下步骤:

  1. 连接数据源。
  2. 分配语句句柄。
  3. 准备并执行SQL语句。
  4. 获取结果集。
  5. 提交事务。
  6. 断开数据源连接并释放环境句柄。

2.3.4 ODBC的工作流程

2.3.4.1. 初始化环境

工作流程开始于应用程序初始化ODBC环境,分配环境句柄。2.3.4.2. 建立连接

  • 应用程序通过以下步骤与数据源建立连接:
  • 分配连接句柄
  • 设置连接属性(可选)
  • 实际连接到数据源
2.3.4.3. 执行SQL语句

连接建立后,应用程序可以:

  • 分配语句句柄
  • 准备SQL语句(可选)
  • 执行SQL语句
  • 处理结果(对于查询)
2.3.4.4. 终止处理

完成数据库操作后:

  • 释放语句句柄
  • 断开与数据源的连接
  • 释放连接句柄
  • 释放环境句柄
2.3.4.4 编程实例

 C语言ODBC示例:

#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <stdio.h>void show_error(SQLHANDLE handle, SQLSMALLINT type) {SQLCHAR sqlstate[6];SQLCHAR message[SQL_MAX_MESSAGE_LENGTH];SQLINTEGER native;SQLSMALLINT len;SQLRETURN ret;printf("Error details:\n");int i = 1;while ((ret = SQLGetDiagRec(type, handle, i, sqlstate, &native, message, sizeof(message), &len)) != SQL_NO_DATA) {printf("%s:%ld:%ld:%s\n", sqlstate, native, len, message);i++;}
}int main() {SQLHENV env;SQLHDBC dbc;SQLHSTMT stmt;SQLRETURN ret;// 1. 分配环境句柄ret = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);if (!SQL_SUCCEEDED(ret)) {printf("Failed to allocate environment handle\n");return 1;}// 设置ODBC版本ret = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);if (!SQL_SUCCEEDED(ret)) {printf("Failed to set ODBC version\n");SQLFreeHandle(SQL_HANDLE_ENV, env);return 1;}// 2. 分配连接句柄ret = SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);if (!SQL_SUCCEEDED(ret)) {printf("Failed to allocate connection handle\n");SQLFreeHandle(SQL_HANDLE_ENV, env);return 1;}// 3. 连接到数据源ret = SQLConnect(dbc, (SQLCHAR*)"YourDSN", SQL_NTS, (SQLCHAR*)"username", SQL_NTS, (SQLCHAR*)"password", SQL_NTS);if (!SQL_SUCCEEDED(ret)) {printf("Failed to connect to data source\n");show_error(dbc, SQL_HANDLE_DBC);SQLFreeHandle(SQL_HANDLE_DBC, dbc);SQLFreeHandle(SQL_HANDLE_ENV, env);return 1;}// 4. 分配语句句柄ret = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);if (!SQL_SUCCEEDED(ret)) {printf("Failed to allocate statement handle\n");SQLDisconnect(dbc);SQLFreeHandle(SQL_HANDLE_DBC, dbc);SQLFreeHandle(SQL_HANDLE_ENV, env);return 1;}// 5. 执行SQL查询ret = SQLExecDirect(stmt, (SQLCHAR*)"SELECT id, name, age FROM employees", SQL_NTS);if (!SQL_SUCCEEDED(ret)) {printf("Failed to execute SQL\n");show_error(stmt, SQL_HANDLE_STMT);} else {// 绑定列SQLINTEGER id, age;SQLCHAR name[50];SQLINTEGER id_ind, age_ind, name_ind;ret = SQLBindCol(stmt, 1, SQL_C_LONG, &id, 0, &id_ind);ret = SQLBindCol(stmt, 2, SQL_C_CHAR, name, sizeof(name), &name_ind);ret = SQLBindCol(stmt, 3, SQL_C_LONG, &age, 0, &age_ind);// 获取结果printf("Employee List:\n");printf("ID\tName\tAge\n");while (SQL_SUCCEEDED(ret = SQLFetch(stmt))) {printf("%d\t%s\t%d\n", id, name, age);}}// 6. 清理SQLFreeHandle(SQL_HANDLE_STMT, stmt);SQLDisconnect(dbc);SQLFreeHandle(SQL_HANDLE_DBC, dbc);SQLFreeHandle(SQL_HANDLE_ENV, env);return 0;
}

Python ODBC示例

import pyodbc# 1. 建立连接
conn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};''SERVER=your_server_name;''DATABASE=your_database_name;''UID=your_username;''PWD=your_password'
)try:# 2. 创建游标cursor = conn.cursor()# 3. 执行SQL查询cursor.execute("SELECT id, name, age FROM employees")# 4. 获取结果print("Employee List:")print("ID\tName\tAge")for row in cursor:print(f"{row.id}\t{row.name}\t{row.age}")# 5. 执行插入操作示例cursor.execute("INSERT INTO employees (name, age) VALUES (?, ?)", "John Doe", 30)conn.commit()print("Insert successful")except pyodbc.Error as e:print(f"Database error: {e}")
finally:# 6. 关闭连接if 'cursor' in locals():cursor.close()if 'conn' in locals():conn.close()
2.3.4.5 常见ODBC函数

1 环境函数:

  • SQLAllocHandle: 分配环境、连接或语句句柄
  • SQLFreeHandle: 释放句柄
  • SQLSetEnvAttr: 设置环境属性

2 连接函数:

  • SQLConnect: 连接到数据源
  • SQLDisconnect: 断开连接
  • SQLDriverConnect: 使用连接字符串连接

3 语句函数:

  • SQLExecDirect: 直接执行SQL语句
  • SQLPrepare/SQLExecute: 准备和执行SQL语句
  • SQLBindCol: 绑定结果列到变量
  • SQLFetch: 获取结果集中的下一行

4 诊断函数:

  • SQLGetDiagRec: 获取诊断记录
  • SQLGetDiagField: 获取诊断字段

2.4 触发器应用场景

#审计日志触发器实现CREATE TRIGGER trg_users_audit
BEFORE UPDATE ON users
FOR EACH ROW
BEGINDECLARE v_user_agent VARCHAR(255);DECLARE v_remote_addr VARCHAR(45);-- 获取连接元数据SELECT @@session.http_user_agent,@@session.http_remote_addr INTO v_user_agent, v_remote_addr;INSERT INTO audit_log (table_name,operation_type,changed_by,client_ip,user_agent,change_time,old_data,new_data) VALUES ('users','UPDATE',USER(),v_remote_addr,v_user_agent,NOW(6),JSON_OBJECT('email', OLD.email,'last_login', OLD.last_login),JSON_OBJECT('email', NEW.email,'last_login', NEW.last_login));
END;

性能优化措施:

  1. 避免在触发器中执行复杂业务逻辑
  2. 使用JSON格式存储变更历史
  3. 异步日志写入机制
  4. 限制审计数据保留周期

3 查询优化技术

3.1 执行计划深度解析

使用EXPLAIN ANALYZE获取真实执行统计:

EXPLAIN ANALYZE
SELECT * FROM orders
WHERE user_id = 12345AND order_date > '2025-01-01'AND status IN ('PAID', 'SHIPPED')
ORDER BY total_amount DESC
LIMIT 10;

关键输出指标解读:

  • actual_time: 实际执行时间(毫秒)
  • loops: 扫描次数
  • rows_produced: 实际输出行数
  • filter_effectiveness: 过滤效率

索引优化策略:

  1. 创建复合索引:ALTER TABLE orders ADD INDEX idx_query (user_id, order_date, status, total_amount)
  2. 索引下推优化:确保WHERE条件字段位于索引前导列
  3. 覆盖索引设计:将SELECT字段全部包含在索引中

3.2 锁机制与并发控制

3.2.1 InnoDB锁内存结构:

# Cstruct lock_t {trx_t* trx;          // 事务指针ulint type_mode;     // 锁模式(LOCK_S/LOCK_X等)dict_index_t* index; // 关联索引dtuple_t* key;       // 锁定的索引键值...
};

3.2.2 死锁检测与避免:

1 事务重试机制:

# java @Retryable(maxAttempts = 3, backoff = @Backoff(delay = 100))
public void updateOrder(Order order) {// 业务逻辑
}

2 乐观锁实现:

UPDATE orders 
SET status = 'SHIPPED',version = version + 1
WHERE order_id = 123 AND version = #{currentVersion};

3.3 索引优化

#创建适当索引-- 单列索引
CREATE INDEX idx_last_name ON employees(last_name);-- 复合索引
CREATE INDEX idx_dept_salary ON employees(department_id, salary DESC);-- 全文索引(用于文本搜索)
CREATE FULLTEXT INDEX idx_product_desc ON products(description);-- 使用不可见索引测试性能
CREATE INDEX idx_test ON employees(hire_date) INVISIBLE;
-- 查询优化器不会使用该索引
ALTER TABLE employees ALTER INDEX idx_test VISIBLE;
3.3.1 分析索引使用情况
-- 查看表索引
SHOW INDEX FROM employees;-- 分析查询执行计划
EXPLAIN ANALYZE
SELECT * FROM employees 
WHERE last_name = 'Smith' AND department_id = 3;-- 索引使用统计
SELECT * FROM sys.schema_index_statistics
WHERE table_schema = 'your_database';

3.4 查询优化

3.4.1 避免全表扫描
-- 不好的写法
SELECT * FROM employees WHERE YEAR(hire_date) = 2020;-- 优化后的写法
SELECT * FROM employees 
WHERE hire_date BETWEEN '2020-01-01' AND '2020-12-31';

3.4.2 使用覆盖索引
-- 需要回表
SELECT * FROM employees WHERE last_name LIKE 'Sm%';-- 使用覆盖索引
SELECT id, last_name FROM employees WHERE last_name LIKE 'Sm%';
3.4.3 分页优化
-- 低效的分页(偏移量大时)
SELECT * FROM employees ORDER BY id LIMIT 10000, 20;-- 高效的分页(使用游标)
SELECT * FROM employees WHERE id > 10000 ORDER BY id LIMIT 20;

相关文章:

第七章 数据库编程

1 数据库编程基础 1.1 数据库系统概述 数据库系统是由数据库、数据库管理系统(DBMS)和应用程序组成的完整系统。其主要目的是高效地存储、管理和检索数据。现代数据库系统通常分为以下几类&#xff1a; 关系型数据库(RDBMS)&#xff1a;如MySQL、PostgreSQL、Oracle等&#x…...

电影感户外哑光人像自拍摄影Lr调色预设,手机滤镜PS+Lightroom预设下载!

调色详情 电影感户外哑光人像自拍摄影 Lr 调色&#xff0c;是借助 Lightroom 软件&#xff0c;针对户外环境下拍摄的人像自拍进行后期处理。旨在模拟电影画面的氛围与质感&#xff0c;通过调色赋予照片独特的艺术气息。强调打造哑光效果&#xff0c;使画面色彩不过于浓烈刺眼&a…...

C++--类的构造函数与初始化列表差异

一&#xff0c;引言 在类中成员函数的构造函数担任其将对象初始化的作用&#xff0c;而初始化列表也有着相似的作用。大部分人建议都是初始化列表进行初始化&#xff0c;本文主要进行讲解二者的区别。 首先看一下构造函数的初始化方式&#xff1a; #define _CRT_SECURE_NO…...

深入浅出之STL源码分析4_类模版

1.引言 我在上面的文章中讲解了vector的基本操作&#xff0c;然后提出了几个问题。 STL之vector基本操作-CSDN博客 1.刚才我提到了我的编译器版本是g 11.4.0&#xff0c;而我们要讲解的是STL&#xff08;标准模板库&#xff09;&#xff0c;那么二者之间的关系是什么&#x…...

Lambda表达式解读

本文通过具体案例演示函数式接口Function<T,R>的三种实现方式演变过程。 一、传统匿名内部类实现 Integer resInt1 t1(new Function<String, Integer>() {Overridepublic Integer apply(String s) {int i Integer.parseInt(s);return i;} });实现特点&#xff1…...

PySide6 GUI 学习笔记——常用类及控件使用方法(常用类边距QMarginsF)

文章目录 类简介方法总览关键说明示例代码 类简介 QMarginsF 用于定义四个浮点型边距&#xff08;左、上、右、下&#xff09;&#xff0c;描述围绕矩形的边框尺寸。所有边距接近零时 isNull() 返回 True&#xff0c;支持运算符重载和数学运算。 方法总览 方法名/运算符参数返…...

Android方法耗时监控插件开发

需求&#xff1a;自定义一个Gradle插件&#xff0c;这个Gradle插件可以统计方法的耗时&#xff0c;并当方法耗时超过阈值时&#xff0c;可以通过打印Log日志在控制台&#xff0c;然后可以通过Log定位到耗时方法的位置&#xff0c;帮助我们找出耗时方法和当前线程名&#xff0c;…...

TWAS / FUSION

FUSION 是一套用于执行转录组范围和调控组范围关联研究&#xff08;TWAS 和 RWAS&#xff09;的工具。它通过构建功能/分子表型的遗传成分的预测模型&#xff0c;并使用 GWAS 汇总统计数据预测和测试该成分与疾病的关联&#xff0c;目标是识别 GWAS 表型与仅在参考数据中测量的…...

C++中的static_cast:类型转换的安全卫士

C中的static_cast&#xff1a;类型转换的安全卫士 在C编程中&#xff0c;类型转换是不可避免的操作&#xff0c;而static_cast作为C四大强制类型转换运算符之一&#xff0c;是最常用且相对安全的一种转换方式。今天我们就来深入探讨一下这个重要的类型转换工具。 一、static_…...

uniapp-商城-51-后台 商家信息(logo处理)

前面对页面基本进行了梳理和说明&#xff0c;特别是对验证规则进行了阐述&#xff0c;并对自定义规则的兼容性进行了特别补充&#xff0c;应该说是干货满满。不知道有没有小伙伴已经消化了。 下面我们继续前进&#xff0c;说说页面上的logo上传组件&#xff0c;主要就是uni-fil…...

04 mysql 修改端口和重置root密码

当我们过了一段时间&#xff0c;忘了自己当初创建的数据库密码和端口&#xff0c;或者端口被占用了&#xff0c;要怎么处理呢 首先&#xff0c;我们先停止mysql。 一、修改端口 打开my.ini文件&#xff0c;搜索port&#xff0c;默认是3306&#xff0c;根据你的需要修改为其他…...

多线程 2 - 死锁问题

死锁 死锁&#xff0c;是多线程代码中的一类经典问题。加锁能够解决线程安全问题&#xff0c;但如果加锁方式不当&#xff0c;就很可能产生死锁。 出现死锁的三种场景 1、一个线程一把锁 就像上篇文章讲过的&#xff0c;如果对同一个线程上了两把锁&#xff0c;而且上的锁是…...

网络原理(Java)

注&#xff1a;此博文为本人学习过程中的笔记 在网络初始中谈到TCP/IP五层模型&#xff0c;接下来我们将介绍这里面涉及到的网络协议。 应用层是程序员接触最多的层次&#xff0c;程序员写的代码只要涉及到网络通信都可以视为是应用层的一部分。应用层里的东西和程序员直接相…...

HDFS 常用基础命令详解——快速上手分布式文件系统

简介&#xff1a; 本文面向刚接触 Hadoop HDFS&#xff08;Hadoop 分布式文件系统&#xff09;的读者&#xff0c;结合 CSDN 博客风格&#xff0c;系统梳理最常用的 HDFS 客户端命令&#xff0c;并配以示例和注意事项&#xff0c;帮助你在开发和运维中快速掌握 HDFS 的文件管理…...

Unity Shaders and Effets Cookbook

目录 作者简介 审稿人简介 前言 我是偏偏 Unity Shaders and Effets Cookbook 第一章&#xff1a;Diffuse Shading - 漫反射着色器 第二章&#xff1a;Using Textures for Effects - 着色器纹理特效的应用 第三章&#xff1a;Making Your Game Shine with Specular - 镜…...

Markdown—LaTeX 数学公式

目录 一、字母1. 希腊大写字母2. 希腊小写字母3. 花体字母 二、上标和下标1. 上标2. 下标3. 其他 三、括号四、数学符号1. 基本数学符号1&#xff09;运算符2&#xff09;常见函数3&#xff09;分式、根号、累加/乘4&#xff09;极限5&#xff09;积分 2. 三角函数与几何符号1&…...

AI 驱动的开发工具

&#x1f527; 主流 AI 前端开发工具 1. GitHub Copilot 由 GitHub 与 OpenAI 联合开发&#xff0c;集成在 Visual Studio Code、JetBrains 等主流 IDE 中&#xff0c;提供智能代码补全、函数生成等功能&#xff0c;极大地提高了开发效率。 (CSDN博客) 2. Cursor 一款 AI 驱…...

【入门】数字走向I

描述 输入整数N&#xff0c;输出相应方阵。 输入描述 一个整数N。&#xff08; 0 < n < 10 ) 输出描述 一个方阵&#xff0c;每个数字的场宽为3。 #include <bits/stdc.h> using namespace std; int main() {int n;cin>>n;for(int i1;i<n*n;i){cout…...

Kubernetes生产实战(十三):灰度发布与蓝绿发布实战指南

在微服务架构中&#xff0c;如何安全高效地发布新版本是每个团队必须掌握的技能。本文将深入讲解Kubernetes中两种主流发布策略的落地实践&#xff0c;附带生产环境真实案例。 一、金丝雀发布&#xff08;灰度发布&#xff09;&#xff1a;渐进式验证新版本 核心思想&#xf…...

数孪实战笔记(1)数字孪生的含义、应用及技术体系

一、含义 数字孪生&#xff08;Digital Twin&#xff09;是一种通过数字化模型在虚拟世界中实时映射和模拟物理实体、系统或过程的技术。它的核心目的是通过对现实对象的建模、感知、分析和预测&#xff0c;实现对物理世界的全面感知、智能控制和优化决策。数字孪生 实体对象 …...

深入浅出之STL源码分析5_类模版实例化与特化

在 C 中&#xff0c;​​类模板的实例化&#xff08;Instantiation&#xff09;和特化&#xff08;Specialization&#xff09;​​ 是模板编程的核心概念&#xff0c;而 ​​显式实例化&#xff08;Explicit Instantiation&#xff09;和隐式实例化&#xff08;Implicit Insta…...

JDBC演进之路:从基础操作到高效连接池

文章目录 一、JDBC 1.0&#xff1a;手动管理的起点1.1 核心特点1.2 代码示例&#xff1a;1.3 痛点分析 二、JDBC 2.0&#xff1a;配置化的升级2.1 核心改进2.2 代码示例2.3 优势与不足 三、JDBC 3.0&#xff1a;连接池的革命3.1 核心改进3.2 代码示例3.3 核心优势 四、版本对比…...

远程调试---在电脑上devtools调试运行在手机上的应用

1、启动项目–以vite项目为例:先ipconfig查看ip地址 ,然后在vite中配置host为ip地址 2、手机上查看项目:保证手机和电脑在同一局域网, 在手机浏览器打开我们vite启动的项目地址, 3、使用chii进行远程调试 (1) 安装 npm install chii -g (2)启动 chii start -p 8080 (3)在…...

街景主观感知全流程(自建数据集+两两对比程序+Trueskill计算评分代码+训练模型+大规模预测)27

目录 0、Emeditor软件1、Place Pluse 2.0数据集2、街景主观感知大框架2.1 街景主观感知&#xff1a;自建数据集2.2 街景主观感知&#xff1a;两两对比程序2.3 街景主观感知&#xff1a;Trueskill评分2.4 街景主观感知&#xff1a;训练模型&#xff0c;Resnet或EfficientNet或V…...

进阶二:基于HC-SR04和LCD1602的超声波测距

一、实验目的 掌握HC-SR04超声波测距模块的工作原理和使用方法。学会使用LCD1602液晶显示屏显示测量数据。熟悉89C51单片机与外设的接口电路设计和编程方法。二、实验原理 1. HC-SR04超声波测距模块原理 HC-SR04超声波测距模块可提供2cm - 400cm的非接触式距离感测功能,测距精…...

单因子实验 方差分析

本文是实验设计与分析&#xff08;第6版&#xff0c;Montgomery著傅珏生译)第3章单因子实验 方差分析python解决方案。本文尽量避免重复书中的理论&#xff0c;着于提供python解决方案&#xff0c;并与原书的运算结果进行对比。您可以从 下载实验设计与分析&#xff08;第6版&a…...

《Python星球日记》 第53天:卷积神经网络(CNN)入门

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、图像表示与通道概念1. 数字图像的本质2. RGB颜色模型3. 图像预处理 二、卷积…...

基于人工智能的个性化 MySQL 学习路径推荐研究

基于人工智能的个性化 MySQL 学习路径推荐研究 摘要: 随着信息技术的飞速发展,数据库在各行业应用广泛,MySQL 作为主流数据库之一,学习需求庞大。然而,不同学习者在知识水平、学习进度和目标上存在差异,传统统一的学习路径难以满足个性化需求。本研究通过运用人工智能技…...

阿里云OSS-服务端加签直传说明/示例(SpringBoot)

目录 概述 OSS文件上传方式 1. OSS控制台上传 2. 客户端直传 3. 后端上传 4. 加签直传 服务端加签方式 1. 服务端生成PostObject所需的签名和Post Policy 2.服务端生成STS临时访问凭证 3. 服务端生成PutObject所需的签名URL 实现1&#xff1a;生成PostObject所需的签…...

《向上生长》读书笔记day5

哎&#xff0c;好像有点坚持不下去了&#xff0c;有点松懈了 不咋想继续写读书笔记&#x1f602;&#xff0c;不过我不可能这么轻易放弃的&#xff0c;起码要做完这一本书&#xff0c;话不多说&#xff0c;开始进入的读书&#x1f4d2;笔记 今天读了两个章节&#xff0c;穷人翻…...

优选算法——队列+BFS

目录 1. N叉树的层序遍历 2. 二叉树的锯齿层序遍历 3. 二叉树最大宽度 4. 在每个树行中找最大值 1. N叉树的层序遍历 题目链接&#xff1a;429. N 叉树的层序遍历 - 力扣&#xff08;LeetCode&#xff09; 题目展示&#xff1a; 题目分析&#xff1a; 层序遍历即可~仅…...

Java MCP 实战 --> AI玩转贪吃蛇

MCP 实战 --> AI玩转贪吃蛇 MCP 更加便捷的扩展了 LLM 的能力&#xff0c;使得 AI 发展更加迅猛。本篇主要为了学习MCP的应用&#xff0c;实现了让AI去玩贪吃蛇&#xff0c;使用 Java 实现了 MCP Server 和 MCP Client 的编码。其他文章如下&#xff1a; thinking 基础版…...

Day20打卡-奇异值SVD分解

今天学习非特征筛选的方法&#xff1a; 知识点回顾&#xff1a; 线性代数概念回顾&#xff08;可不掌握&#xff09;奇异值推导&#xff08;可不掌握&#xff09;奇异值的应用 特征降维&#xff1a;对高维数据减小计算量、可视化数据重构&#xff1a;比如重构信号、重构图像&am…...

【RT-Thread Studio】nor flash配置Fal分区

前置条件&#xff1a;【RT-Thread Studio】W25Q128配置 添加 FAL软件包 配置SFUD驱动程序&#xff0c;使用FAL的设备为W25Q128 将fal_cfg.h和fal_flash_sfud_port.c提取出来&#xff0c;放到自己创建的fal_porting目录。 修改 fal_flash_sfud_port.c struct fal_flash_dev n…...

在资源受限设备上实现手势识别:基于包络EMG数据和实时测试的Tiny-ML方法

英文标题&#xff1a;Enabling Gesture on a Resource-Constrained Device: A Tiny-ML Approach with Envelope EMG Data and Real-Time Testing 中文标题&#xff1a;在资源受限设备上实现手势识别&#xff1a;基于包络EMG数据和实时测试的Tiny-ML方法 作者信息 Mohsin Ali S…...

动态规划:最长递增子序列

给定一个数组&#xff0c;求最长递增子序列的长度,就是要求我们求出一个序列中最长的上升子序列的长度&#xff0c;最长上升子序列的定义就是从原序列中按照孙旭去除一些数字&#xff0c;这些数字是逐渐增大的。 *定义dp[i]表示以第i个元素结尾的最长上升子序列的长度。 *初始…...

贪心算法专题(Part2)

目录 1. 最优除法 2. 加油站 3. 坏了的计算器 4. 可被三整除的最大和 5. 单调递增的数字 6. 合并区间 7. 无重叠区间 8. 用最少数量的箭引爆气球 1. 最优除法 题目链接&#xff1a;553. 最优除法 - 力扣&#xff08;LeetCode&#xff09; 题目展示&#xff1a; 题目分…...

4.9/Q1,GBD数据库最新文章解读

文章题目&#xff1a;The burden of diseases attributable to high body mass index in Asia from 1990 - 2019: results from the global burden of disease study 2019 DOI&#xff1a;10.1080/07853890.2025.2483977 中文标题&#xff1a;1990 年至 2019 年亚洲高体重指数导…...

API 网关核心功能解析:负载均衡、容灾、削峰降级原理与实战摘要

在微服务架构中&#xff0c;API 网关作为流量入口枢纽&#xff0c;通过负载均衡、容灾、削峰降级等核心功能保障系统稳定性与高可用性。本文结合 Spring Cloud Gateway 实战代码、原理剖析及行业最佳实践&#xff0c;深度解析网关核心能力&#xff0c;并对比当前前沿技术方案&a…...

Spring之AOP

什么是AOP AOP:Aspect 0riented Programming(面向切面编程、面向方面编程)&#xff0c;可简单理解为就是面向特定方法编程。 场景:案例中部分业务方法运行较慢&#xff0c;定位执行耗时较长的接口&#xff0c;此时需要统计每一个业务方法的 执行耗时。 优势: 1.减少重复代…...

TransmittableThreadLocal:穿透线程边界的上下文传递艺术

文章目录 前言一、如何线程上下文传递1.1 ThreadLocal单线程1.2 InheritableThreadLocal的继承困境1.3 TTL的时空折叠术 二、TTL核心设计解析2.1 时空快照机制2.2 装饰器模式2.3 采用自动清理机制 三、设计思想启示四、实践启示录结语 前言 在并发编程领域&#xff0c;线程上下…...

基于STM32的甲醛检测

一、制作目标 以正点原子的miniSTM32F103RCT6开发板为主控&#xff0c;使用甲醛传感器检测环境空气中的甲醛含量&#xff08;以mg/m^3为单位&#xff09;、C02含量&#xff08;以ppm为单位&#xff09;和总有机挥发物含量TVOC&#xff08;以mg/m^3为单位&#xff09;在OLED显示…...

人形机器人:主控芯片

目前人形机器人领域的主控芯片因厂商和应用场景不同而有所差异&#xff0c;以下是一些主要人形机器人及其可能使用的主控芯片概况&#xff0c;基于公开信息和行业趋势。由于具体型号常为商业机密&#xff0c;部分信息为推测&#xff1a; 主要人形机器人及其主控芯片 特斯拉&am…...

Web自动化测试入门详解

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、目的 web自动化测试作为软件自动化测试领域中绕不过去的一个“香饽饽”&#xff0c;通常都会作为广大测试从业者的首选学习对象&#xff0c;相较于C/S架…...

数据结构:树(树的定义和基本术语)

非空树&#xff1a;有且仅有一个根节点 空树&#xff1a;节点数为0的树 在非空树中根节点没有前驱&#xff0c;叶子结点&#xff08;终端结点&#xff09;没有后继&#xff0c;分支结点&#xff08;非终端结点&#xff09;前驱和后继都有&#xff0c;前驱有且仅有一个。 下图…...

用jsp简单实现C语言标准化测试系统

C语言标准化测试系统 在Web编程技术的学习过程中&#xff0c;我们小组为了深入理解相关技术原理&#xff0c;提升实践能力&#xff0c;开发了一个基于动态Web工程框架的C语言标准化考试系统。现在&#xff0c;就来和大家分享一下我们的项目经历。 一、实验目的剖析 这个项目…...

牛客周赛round91

C 若序列为1 4 5 7 9 1 2 3&#xff0c;1 9一定大于1 1或1 4...所以只需要记录当前数之前数字的最大值&#xff0c;然后遍历取max即可&#xff0c;所以对于上面的序列有效的比较为1 9&#xff0c;2 9&#xff0c;3 9取max 代码 //求大于当前数的最大值&#xff0c;然后…...

java-代理

1.什么是java代理模式&#xff1f; 给目标对象提供一个代理对象&#xff0c;并且由代理对象控制对目标对象的引用 我们可以这样理解 我们是用户&#xff0c;代理类是支付宝&#xff0c;我们想用支付宝的转账功能&#xff0c;但是支付宝本身没有转账功能&#xff0c; 又恰好…...

【数据结构与算法】图的基本概念与遍历

目录 一、图的基本概念 1.1 图的基本组成 1.2 图的分类 1.3 顶点的度数 1.4 路径与回路 1.5 子图与特殊图 二. 图的存储结构 2.1 邻接矩阵 2.2 邻接表 三、深度优先遍历 3.1 原理 3.2 实现步骤 3.3 代码实现 四、广度优先遍历 4.1 原理 4.2 实现步骤 4.3 代码…...

《AI大模型应知应会100篇》第54篇:国产大模型API对比与使用指南

第54篇&#xff1a;国产大模型API对比与使用指南 ——从百度文心到通义千问&#xff0c;一文看懂国内AI平台选型 &#x1f4cc; 摘要 随着中国人工智能产业的快速发展&#xff0c;越来越多的国产大模型平台开始崭露头角。本文将系统梳理当前主流国产大模型 API&#xff08;如…...