SQL中的存储过程怎么优化,有哪些方式?

1、优化方式

(1)使用合适的索引

确保存储过程中使用的查询都能利用到合适的索引。索引可以显著提高查询的查找速度。

(2)避免不必要的复杂计算

尽量避免在存储过程中进行不必要的复杂计算,可以将一些重复计算提前在应用层预处理。

(3)减少临时表的使用

虽然临时表有时能简化处理,但频繁的创建和删除临时表会增加开销。尽量减少临时表的使用,或者使用适当的索引和优化查询来替代。

(4)避免使用游标

游标会逐行处理数据,这在大数据量时性能较差。尽量使用集合操作替代游标。

(5)合理使用批量操作

将多次单条记录操作合并为一次批量操作,减少SQL执行次数,降低网络和数据库的开销。

(6)提高并行度

将一些可以并行执行的任务分离出来,充分利用多核CPU的优势。

2、示例

(1)使用合适的索引

-- 创建索引
CREATE INDEX idx_user_email ON users(email);

-- 优化前的存储过程
DELIMITER //
CREATE PROCEDURE GetUserByEmail(IN userEmail VARCHAR(255))
BEGIN
    SELECT * FROM users WHERE email = userEmail;
END //
DELIMITER ;

-- 优化后的存储过程(使用索引)
DELIMITER //
CREATE PROCEDURE GetUserByEmail(IN userEmail VARCHAR(255))
BEGIN
    SELECT * FROM users WHERE email = userEmail;
END //
DELIMITER ;

 (2)避免不必要的复杂计算

-- 优化前的存储过程:
DELIMITER //
CREATE PROCEDURE CalculateTotalSalary(IN departmentId INT)
BEGIN
    DECLARE totalSalary DECIMAL(10, 2);
    SELECT SUM(salary) INTO totalSalary 
    FROM employees 
    WHERE department_id = departmentId;
    
    SELECT totalSalary, totalSalary * 0.2 AS bonus 
    FROM dual;
END //
DELIMITER ;

-- 优化后的存储过程(避免重复计算):
DELIMITER //
CREATE PROCEDURE CalculateTotalSalary(IN departmentId INT)
BEGIN
    DECLARE totalSalary DECIMAL(10, 2);
    DECLARE bonus DECIMAL(10, 2);
    
    SELECT SUM(salary) INTO totalSalary 
    FROM employees 
    WHERE department_id = departmentId;
    
    SET bonus = totalSalary * 0.2;
    
    SELECT totalSalary, bonus FROM dual;
END //
DELIMITER ;

(3)减少临时表的使用

-- 优化前的存储过程:
DELIMITER //
CREATE PROCEDURE GetHighSalaryEmployees()
BEGIN
    CREATE TEMPORARY TABLE TempEmployees AS
    SELECT * FROM employees WHERE salary > 100000;
    
    SELECT * FROM TempEmployees;
    
    DROP TEMPORARY TABLE TempEmployees;
END //
DELIMITER ;


-- 优化后的存储过程(直接查询):
DELIMITER //
CREATE PROCEDURE GetHighSalaryEmployees()
BEGIN
    SELECT * FROM employees WHERE salary > 100000;
END //
DELIMITER ;

(4)避免使用游标

-- 优化前的存储过程:
DELIMITER //
CREATE PROCEDURE SumSalaries()
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE emp_salary DECIMAL(10, 2);
    DECLARE totalSalary DECIMAL(10, 2) DEFAULT 0;
    DECLARE emp_cursor CURSOR FOR SELECT salary FROM employees;
    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
    
    OPEN emp_cursor;
    
    read_loop: LOOP
        FETCH emp_cursor INTO emp_salary;
        IF done THEN
            LEAVE read_loop;
        END IF;
        SET totalSalary = totalSalary + emp_salary;
    END LOOP;
    
    CLOSE emp_cursor;
    
    SELECT totalSalary;
END //
DELIMITER ;

-- 优化后的存储过程(使用集合操作):
DELIMITER //
CREATE PROCEDURE SumSalaries()
BEGIN
    DECLARE totalSalary DECIMAL(10, 2);
    SELECT SUM(salary) INTO totalSalary FROM employees;
    SELECT totalSalary;
END //
DELIMITER ;

(5)合理使用批量操作

-- 优化前的存储过程:
DELIMITER //
CREATE PROCEDURE InsertEmployees(IN employeeList JSON)
BEGIN
    DECLARE i INT DEFAULT 0;
    DECLARE total INT;
    SET total = JSON_LENGTH(employeeList);
    
    WHILE i < total DO
        INSERT INTO employees (name, salary) 
        VALUES (JSON_UNQUOTE(JSON_EXTRACT(employeeList, CONCAT('$[', i, '].name'))),
                JSON_UNQUOTE(JSON_EXTRACT(employeeList, CONCAT('$[', i, '].salary'))));
        SET i = i + 1;
    END WHILE;
END //
DELIMITER ;

-- 优化后的存储过程(批量插入):
DELIMITER //
CREATE PROCEDURE InsertEmployees(IN employeeList JSON)
BEGIN
    DECLARE i INT DEFAULT 0;
    DECLARE total INT;
    DECLARE name VARCHAR(255);
    DECLARE salary DECIMAL(10, 2);
    SET total = JSON_LENGTH(employeeList);
    
    INSERT INTO employees (name, salary)
    SELECT JSON_UNQUOTE(JSON_EXTRACT(employeeList, CONCAT('$[', number, '].name'))),
           JSON_UNQUOTE(JSON_EXTRACT(employeeList, CONCAT('$[', number, '].salary')))
    FROM (
        SELECT @rownum := @rownum + 1 AS number 
        FROM (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) t1,
             (SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) t2,
             (SELECT @rownum := 0) t3
        LIMIT total
    ) numbers;
END //
DELIMITER ;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值