内容简介:本文主要介绍MariaDB复杂报表SQL的开发技巧和性能优化方法,包括报表SQL的特点、复杂查询的执行原理、索引策略优化等核心内容。通过实际案例讲解销售报表、财务报表、库存报表的开发过程,以及如何优化报表查询性能。风哥教程参考MariaDB官方文档SQL Syntax、Optimization等相关内容。
Part01-基础概念与理论知识
1.1 报表SQL的特点与挑战
报表SQL具有以下特点:
- 数据量庞大:通常需要处理大量历史数据
- 查询复杂:涉及多表关联、聚合计算、分组排序等
- 性能要求高:用户期望报表生成速度快
- 数据准确性:报表数据必须准确无误
面临的挑战:
- 查询性能瓶颈:复杂查询可能导致执行时间过长
- 资源消耗大:内存、CPU、I/O等资源消耗较高
- 并发访问压力:多用户同时访问报表系统
- 数据一致性:确保报表数据的实时性和一致性
1.2 复杂查询的执行原理
MariaDB执行复杂查询的过程:
- 解析SQL语句:将SQL转换为解析树
- 优化器生成执行计划:选择最佳执行路径
- 执行查询:按照执行计划执行操作
- 返回结果:将结果集返回给客户端
影响执行性能的因素:
- 索引使用情况
- 表关联方式
- 聚合函数的使用
- 排序和分组操作
- 子查询的嵌套层级
1.3 性能优化的基本原理
性能优化的核心原则:
- 减少数据扫描范围:使用索引、分区表等
- 优化查询计划:避免全表扫描、避免临时表
- 减少数据传输:只查询必要的列、使用分页
- 合理使用缓存:利用查询缓存、结果缓存
- 优化硬件资源:增加内存、使用SSD等
更多视频教程www.fgedu.net.cn
Part02-生产环境规划与建议
2.1 报表系统架构设计
生产环境报表系统架构建议:
- 专用报表数据库:将报表查询与业务数据库分离
- 数据仓库:使用数据仓库存储历史数据
- ETL流程:定期将业务数据同步到报表数据库
- 缓存层:使用Redis等缓存报表结果
- 监控系统:监控报表查询性能
2.2 索引策略优化
更多学习教程公众号风哥教程itpux_com
# 查看表索引
MariaDB [fgedudb]> SHOW INDEX FROM fgedu_sales;
+———-+————+——————+————–+————-+———–+————-+———-+——–+——+————+———+—————+———+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Ignored |
+———-+————+——————+————–+————-+———–+————-+———-+——–+——+————+———+—————+———+
| fgedu_sales | 0 | PRIMARY | 1 | id | A | 10000 | NULL | NULL | | BTREE | | | NO |
| fgedu_sales | 1 | idx_sale_date | 1 | sale_date | A | 3650 | NULL | NULL | | BTREE | | | NO |
| fgedu_sales | 1 | idx_customer_id | 1 | customer_id | A | 2000 | NULL | NULL | | BTREE | | | NO |
+———-+————+——————+————–+————-+———–+————-+———-+——–+——+————+———+—————+———+
MariaDB [fgedudb]> SHOW INDEX FROM fgedu_sales;
+———-+————+——————+————–+————-+———–+————-+———-+——–+——+————+———+—————+———+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Ignored |
+———-+————+——————+————–+————-+———–+————-+———-+——–+——+————+———+—————+———+
| fgedu_sales | 0 | PRIMARY | 1 | id | A | 10000 | NULL | NULL | | BTREE | | | NO |
| fgedu_sales | 1 | idx_sale_date | 1 | sale_date | A | 3650 | NULL | NULL | | BTREE | | | NO |
| fgedu_sales | 1 | idx_customer_id | 1 | customer_id | A | 2000 | NULL | NULL | | BTREE | | | NO |
+———-+————+——————+————–+————-+———–+————-+———-+——–+——+————+———+—————+———+
索引设计建议:
- 为报表查询的过滤条件创建索引
- 为经常排序和分组的列创建索引
- 使用复合索引提高多条件查询性能
- 定期维护索引:重建碎片化的索引
2.3 资源配置建议
# 查看当前配置
MariaDB [(none)]> SHOW VARIABLES LIKE ‘%buffer%’;
+————————————-+—————-+
| Variable_name | Value |
+————————————-+—————-+
| innodb_buffer_pool_size | 1073741824 |
| innodb_log_buffer_size | 16777216 |
| join_buffer_size | 262144 |
| key_buffer_size | 8388608 |
| read_buffer_size | 131072 |
| read_rnd_buffer_size | 262144 |
| sort_buffer_size | 2097152 |
+————————————-+—————-+
MariaDB [(none)]> SHOW VARIABLES LIKE ‘%buffer%’;
+————————————-+—————-+
| Variable_name | Value |
+————————————-+—————-+
| innodb_buffer_pool_size | 1073741824 |
| innodb_log_buffer_size | 16777216 |
| join_buffer_size | 262144 |
| key_buffer_size | 8388608 |
| read_buffer_size | 131072 |
| read_rnd_buffer_size | 262144 |
| sort_buffer_size | 2097152 |
+————————————-+—————-+
生产环境资源配置建议:
- 增大innodb_buffer_pool_size:建议设置为物理内存的50-80%
- 调整sort_buffer_size和join_buffer_size:根据查询复杂度调整
- 设置合适的tmp_table_size和max_heap_table_size:避免临时表溢出到磁盘
- 使用SSD存储:提高I/O性能
- 增加CPU核心数:提高并发处理能力
学习交流加群风哥微信: itpux-com
Part03-生产环境项目实施方案
3.1 报表SQL开发规范
报表SQL开发的最佳实践:
- 使用明确的表别名:提高可读性
- 只查询必要的列:减少数据传输
- 合理使用WHERE子句:减少数据扫描范围
- 避免使用SELECT *:只选择需要的列
- 使用参数化查询:提高安全性和性能
- 添加适当的注释:提高可维护性
3.2 性能测试与调优
# 使用EXPLAIN分析执行计划
MariaDB [fgedudb]> EXPLAIN SELECT c.name, SUM(s.amount) as total_sales
FROM fgedu_customers c
JOIN fgedu_sales s ON c.id = s.customer_id
WHERE s.sale_date BETWEEN ‘2023-01-01’ AND ‘2023-12-31’
GROUP BY c.name
ORDER BY total_sales DESC;
+—-+————-+——-+————+——+——————+——————+———+—————-+——+———-+———————————+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+——-+————+——+——————+——————+———+—————-+——+———-+———————————+
| 1 | SIMPLE | s | NULL | range | idx_sale_date | idx_sale_date | 3 | NULL | 1000 | 100.00 | Using index condition;
Using temporary;
Using filesort |
| 1 | SIMPLE | c | NULL | eq_ref | PRIMARY | PRIMARY | 4 | fgedudb.s.customer_id | 1 | 100.00 | NULL |
+—-+————-+——-+————+——+——————+——————+———+—————-+——+———-+———————————+
MariaDB [fgedudb]> EXPLAIN SELECT c.name, SUM(s.amount) as total_sales
FROM fgedu_customers c
JOIN fgedu_sales s ON c.id = s.customer_id
WHERE s.sale_date BETWEEN ‘2023-01-01’ AND ‘2023-12-31’
GROUP BY c.name
ORDER BY total_sales DESC;
+—-+————-+——-+————+——+——————+——————+———+—————-+——+———-+———————————+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+——-+————+——+——————+——————+———+—————-+——+———-+———————————+
| 1 | SIMPLE | s | NULL | range | idx_sale_date | idx_sale_date | 3 | NULL | 1000 | 100.00 | Using index condition;
Using temporary;
Using filesort |
| 1 | SIMPLE | c | NULL | eq_ref | PRIMARY | PRIMARY | 4 | fgedudb.s.customer_id | 1 | 100.00 | NULL |
+—-+————-+——-+————+——+——————+——————+———+—————-+——+———-+———————————+
性能调优步骤:
- 使用EXPLAIN分析执行计划
- 识别性能瓶颈:全表扫描、临时表、文件排序等
- 优化索引:添加缺失的索引
- 重写SQL:优化查询逻辑
- 测试性能:比较优化前后的执行时间
3.3 报表缓存策略
报表缓存策略建议:
- 使用应用层缓存:将报表结果缓存到Redis等缓存系统
- 设置合理的缓存过期时间:根据数据更新频率调整
- 使用增量缓存:只缓存新增数据
- 预计算:定期计算并缓存常用报表
- 使用物化视图:存储预计算的结果
学习交流加群风哥QQ113257174
Part04-生产案例与实战讲解
4.1 销售报表开发实战
场景描述:生成月度销售报表,按客户和产品分组统计销售额。
# 创建销售表和相关表
CREATE TABLE fgedu_customers (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(100)
);
CREATE TABLE fgedu_products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL
);
CREATE TABLE fgedu_sales (
id INT PRIMARY KEY AUTO_INCREMENT,
customer_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL,
amount DECIMAL(10,2) NOT NULL,
sale_date DATE NOT NULL,
FOREIGN KEY (customer_id) REFERENCES fgedu_customers(id),
FOREIGN KEY (product_id) REFERENCES fgedu_products(id)
);
# 创建索引
CREATE INDEX idx_sale_date ON fgedu_sales(sale_date);
CREATE INDEX idx_customer_id ON fgedu_sales(customer_id);
CREATE INDEX idx_product_id ON fgedu_sales(product_id);
CREATE TABLE fgedu_customers (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(100)
);
CREATE TABLE fgedu_products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10,2) NOT NULL
);
CREATE TABLE fgedu_sales (
id INT PRIMARY KEY AUTO_INCREMENT,
customer_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL,
amount DECIMAL(10,2) NOT NULL,
sale_date DATE NOT NULL,
FOREIGN KEY (customer_id) REFERENCES fgedu_customers(id),
FOREIGN KEY (product_id) REFERENCES fgedu_products(id)
);
# 创建索引
CREATE INDEX idx_sale_date ON fgedu_sales(sale_date);
CREATE INDEX idx_customer_id ON fgedu_sales(customer_id);
CREATE INDEX idx_product_id ON fgedu_sales(product_id);
执行结果:
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.02 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.02 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
# 插入测试数据
INSERT INTO fgedu_customers (name, email) VALUES
(‘张三’, ‘zhangsan@fgedu.net.cn’),
(‘李四’, ‘lisi@fgedu.net.cn’),
(‘王五’, ‘wangwu@fgedu.net.cn’);
INSERT INTO fgedu_products (name, price) VALUES
(‘产品A’, 100.00),
(‘产品B’, 200.00),
(‘产品C’, 300.00);
INSERT INTO fgedu_sales (customer_id, product_id, quantity, amount, sale_date) VALUES
(1, 1, 10, 1000.00, ‘2023-01-01’),
(1, 2, 5, 1000.00, ‘2023-01-02’),
(2, 1, 8, 800.00, ‘2023-01-03’),
(2, 3, 3, 900.00, ‘2023-01-04’),
(3, 2, 6, 1200.00, ‘2023-01-05’),
(3, 3, 2, 600.00, ‘2023-01-06’);
INSERT INTO fgedu_customers (name, email) VALUES
(‘张三’, ‘zhangsan@fgedu.net.cn’),
(‘李四’, ‘lisi@fgedu.net.cn’),
(‘王五’, ‘wangwu@fgedu.net.cn’);
INSERT INTO fgedu_products (name, price) VALUES
(‘产品A’, 100.00),
(‘产品B’, 200.00),
(‘产品C’, 300.00);
INSERT INTO fgedu_sales (customer_id, product_id, quantity, amount, sale_date) VALUES
(1, 1, 10, 1000.00, ‘2023-01-01’),
(1, 2, 5, 1000.00, ‘2023-01-02’),
(2, 1, 8, 800.00, ‘2023-01-03’),
(2, 3, 3, 900.00, ‘2023-01-04’),
(3, 2, 6, 1200.00, ‘2023-01-05’),
(3, 3, 2, 600.00, ‘2023-01-06’);
执行结果:
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
Query OK, 6 rows affected (0.01 sec)
Records: 6 Duplicates: 0 Warnings: 0
Records: 3 Duplicates: 0 Warnings: 0
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
Query OK, 6 rows affected (0.01 sec)
Records: 6 Duplicates: 0 Warnings: 0
# 生成月度销售报表
SELECT
c.name AS customer_name,
p.name AS product_name,
SUM(s.quantity) AS total_quantity,
SUM(s.amount) AS total_amount
FROM
fgedu_sales s
JOIN
fgedu_customers c ON s.customer_id = c.id
JOIN
fgedu_products p ON s.product_id = p.id
WHERE
s.sale_date BETWEEN ‘2023-01-01’ AND ‘2023-01-31’
GROUP BY
c.name, p.name
ORDER BY
total_amount DESC;
SELECT
c.name AS customer_name,
p.name AS product_name,
SUM(s.quantity) AS total_quantity,
SUM(s.amount) AS total_amount
FROM
fgedu_sales s
JOIN
fgedu_customers c ON s.customer_id = c.id
JOIN
fgedu_products p ON s.product_id = p.id
WHERE
s.sale_date BETWEEN ‘2023-01-01’ AND ‘2023-01-31’
GROUP BY
c.name, p.name
ORDER BY
total_amount DESC;
执行结果:
+—————+————–+—————-+————-+
| customer_name | product_name | total_quantity | total_amount |
+—————+————–+—————-+————-+
| 张三 | 产品B | 5 | 1000.00 |
| 张三 | 产品A | 10 | 1000.00 |
| 王五 | 产品B | 6 | 1200.00 |
| 李四 | 产品C | 3 | 900.00 |
| 李四 | 产品A | 8 | 800.00 |
| 王五 | 产品C | 2 | 600.00 |
+—————+————–+—————-+————-+
| customer_name | product_name | total_quantity | total_amount |
+—————+————–+—————-+————-+
| 张三 | 产品B | 5 | 1000.00 |
| 张三 | 产品A | 10 | 1000.00 |
| 王五 | 产品B | 6 | 1200.00 |
| 李四 | 产品C | 3 | 900.00 |
| 李四 | 产品A | 8 | 800.00 |
| 王五 | 产品C | 2 | 600.00 |
+—————+————–+—————-+————-+
4.2 财务报表开发实战
场景描述:生成月度财务报表,统计收入、支出和利润。
# 创建财务表
CREATE TABLE fgedu_financial_transactions (
id INT PRIMARY KEY AUTO_INCREMENT,
type ENUM(‘income’, ‘expense’) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
category VARCHAR(50) NOT NULL,
transaction_date DATE NOT NULL,
description VARCHAR(200)
);
# 创建索引
CREATE INDEX idx_transaction_date ON fgedu_financial_transactions(transaction_date);
CREATE INDEX idx_type ON fgedu_financial_transactions(type);
CREATE TABLE fgedu_financial_transactions (
id INT PRIMARY KEY AUTO_INCREMENT,
type ENUM(‘income’, ‘expense’) NOT NULL,
amount DECIMAL(10,2) NOT NULL,
category VARCHAR(50) NOT NULL,
transaction_date DATE NOT NULL,
description VARCHAR(200)
);
# 创建索引
CREATE INDEX idx_transaction_date ON fgedu_financial_transactions(transaction_date);
CREATE INDEX idx_type ON fgedu_financial_transactions(type);
执行结果:
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
# 插入测试数据
INSERT INTO fgedu_financial_transactions (type, amount, category, transaction_date, description) VALUES
(‘income’, 50000.00, ‘sales’, ‘2023-01-01’, ‘产品销售’),
(‘income’, 10000.00, ‘investment’, ‘2023-01-05’, ‘投资收益’),
(‘expense’, 20000.00, ‘salary’, ‘2023-01-10’, ‘员工工资’),
(‘expense’, 5000.00, ‘rent’, ‘2023-01-15’, ‘办公室租金’),
(‘expense’, 3000.00, ‘utilities’, ‘2023-01-20’, ‘水电费’),
(‘income’, 15000.00, ‘sales’, ‘2023-01-25’, ‘产品销售’);
INSERT INTO fgedu_financial_transactions (type, amount, category, transaction_date, description) VALUES
(‘income’, 50000.00, ‘sales’, ‘2023-01-01’, ‘产品销售’),
(‘income’, 10000.00, ‘investment’, ‘2023-01-05’, ‘投资收益’),
(‘expense’, 20000.00, ‘salary’, ‘2023-01-10’, ‘员工工资’),
(‘expense’, 5000.00, ‘rent’, ‘2023-01-15’, ‘办公室租金’),
(‘expense’, 3000.00, ‘utilities’, ‘2023-01-20’, ‘水电费’),
(‘income’, 15000.00, ‘sales’, ‘2023-01-25’, ‘产品销售’);
执行结果:
Query OK, 6 rows affected (0.01 sec)
Records: 6 Duplicates: 0 Warnings: 0
Records: 6 Duplicates: 0 Warnings: 0
# 生成月度财务报表
SELECT
‘2023-01’ AS month,
SUM(CASE WHEN type = ‘income’ THEN amount ELSE 0 END) AS total_income,
SUM(CASE WHEN type = ‘expense’ THEN amount ELSE 0 END) AS total_expense,
SUM(CASE WHEN type = ‘income’ THEN amount ELSE -amount END) AS net_profit
FROM
fgedu_financial_transactions
WHERE
transaction_date BETWEEN ‘2023-01-01’ AND ‘2023-01-31’
UNION ALL
SELECT
‘2023-01’ AS month,
category,
SUM(CASE WHEN type = ‘income’ THEN amount ELSE 0 END) AS amount,
SUM(CASE WHEN type = ‘expense’ THEN amount ELSE 0 END) AS amount
FROM
fgedu_financial_transactions
WHERE
transaction_date BETWEEN ‘2023-01-01’ AND ‘2023-01-31’
GROUP BY
category
ORDER BY
net_profit DESC;
SELECT
‘2023-01’ AS month,
SUM(CASE WHEN type = ‘income’ THEN amount ELSE 0 END) AS total_income,
SUM(CASE WHEN type = ‘expense’ THEN amount ELSE 0 END) AS total_expense,
SUM(CASE WHEN type = ‘income’ THEN amount ELSE -amount END) AS net_profit
FROM
fgedu_financial_transactions
WHERE
transaction_date BETWEEN ‘2023-01-01’ AND ‘2023-01-31’
UNION ALL
SELECT
‘2023-01’ AS month,
category,
SUM(CASE WHEN type = ‘income’ THEN amount ELSE 0 END) AS amount,
SUM(CASE WHEN type = ‘expense’ THEN amount ELSE 0 END) AS amount
FROM
fgedu_financial_transactions
WHERE
transaction_date BETWEEN ‘2023-01-01’ AND ‘2023-01-31’
GROUP BY
category
ORDER BY
net_profit DESC;
执行结果:
+——-+————-+————–+————+
| month | total_income | total_expense | net_profit |
+——-+————-+————–+————+
| 2023-01 | 75000.00 | 28000.00 | 47000.00 |
| 2023-01 | sales | 65000.00 | 0.00 |
| 2023-01 | investment | 10000.00 | 0.00 |
| 2023-01 | salary | 0.00 | 20000.00 |
| 2023-01 | rent | 0.00 | 5000.00 |
| 2023-01 | utilities | 0.00 | 3000.00 |
+——-+————-+————–+————+
| month | total_income | total_expense | net_profit |
+——-+————-+————–+————+
| 2023-01 | 75000.00 | 28000.00 | 47000.00 |
| 2023-01 | sales | 65000.00 | 0.00 |
| 2023-01 | investment | 10000.00 | 0.00 |
| 2023-01 | salary | 0.00 | 20000.00 |
| 2023-01 | rent | 0.00 | 5000.00 |
| 2023-01 | utilities | 0.00 | 3000.00 |
+——-+————-+————–+————+
4.3 库存报表开发实战
场景描述:生成库存状态报表,统计产品库存数量和价值。
# 创建库存表
CREATE TABLE fgedu_inventory (
id INT PRIMARY KEY AUTO_INCREMENT,
product_id INT NOT NULL,
quantity INT NOT NULL,
last_update_date DATE NOT NULL,
FOREIGN KEY (product_id) REFERENCES fgedu_products(id)
);
# 创建索引
CREATE INDEX idx_product_id ON fgedu_inventory(product_id);
CREATE TABLE fgedu_inventory (
id INT PRIMARY KEY AUTO_INCREMENT,
product_id INT NOT NULL,
quantity INT NOT NULL,
last_update_date DATE NOT NULL,
FOREIGN KEY (product_id) REFERENCES fgedu_products(id)
);
# 创建索引
CREATE INDEX idx_product_id ON fgedu_inventory(product_id);
执行结果:
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
# 插入测试数据
INSERT INTO fgedu_inventory (product_id, quantity, last_update_date) VALUES
(1, 100, ‘2023-01-01’),
(2, 50, ‘2023-01-01’),
(3, 30, ‘2023-01-01’);
INSERT INTO fgedu_inventory (product_id, quantity, last_update_date) VALUES
(1, 100, ‘2023-01-01’),
(2, 50, ‘2023-01-01’),
(3, 30, ‘2023-01-01’);
执行结果:
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
Records: 3 Duplicates: 0 Warnings: 0
# 生成库存报表
SELECT
p.id AS product_id,
p.name AS product_name,
p.price AS unit_price,
i.quantity AS stock_quantity,
(p.price * i.quantity) AS stock_value,
i.last_update_date
FROM
fgedu_products p
JOIN
fgedu_inventory i ON p.id = i.product_id
ORDER BY
stock_value DESC;
SELECT
p.id AS product_id,
p.name AS product_name,
p.price AS unit_price,
i.quantity AS stock_quantity,
(p.price * i.quantity) AS stock_value,
i.last_update_date
FROM
fgedu_products p
JOIN
fgedu_inventory i ON p.id = i.product_id
ORDER BY
stock_value DESC;
执行结果:
+————+————–+———–+—————-+————-+——————+
| product_id | product_name | unit_price | stock_quantity | stock_value | last_update_date |
+————+————–+———–+—————-+————-+——————+
| 3 | 产品C | 300.00 | 30 | 9000.00 | 2023-01-01 |
| 1 | 产品A | 100.00 | 100 | 10000.00 | 2023-01-01 |
| 2 | 产品B | 200.00 | 50 | 10000.00 | 2023-01-01 |
+————+————–+———–+—————-+————-+——————+
| product_id | product_name | unit_price | stock_quantity | stock_value | last_update_date |
+————+————–+———–+—————-+————-+——————+
| 3 | 产品C | 300.00 | 30 | 9000.00 | 2023-01-01 |
| 1 | 产品A | 100.00 | 100 | 10000.00 | 2023-01-01 |
| 2 | 产品B | 200.00 | 50 | 10000.00 | 2023-01-01 |
+————+————–+———–+—————-+————-+——————+
风哥提示:安全开发是防止SQL注入的第一道防线
Part05-风哥经验总结与分享
5.1 报表SQL最佳实践
风哥提示:在开发报表SQL时,应优先考虑查询性能,避免使用复杂的子查询和不必要的关联操作。
- 使用适当的聚合函数:SUM、COUNT、AVG等
- 合理使用窗口函数:ROW_NUMBER、RANK、DENSE_RANK等
- 避免在WHERE子句中使用函数:会导致索引失效
- 使用CTE(公用表表达式):提高复杂查询的可读性
- 定期分析表:更新统计信息,帮助优化器生成更好的执行计划
5.2 性能优化技巧
- 使用分区表:将大表按时间或其他维度分区
- 预计算汇总数据:创建汇总表存储计算结果
- 使用物化视图:存储复杂查询的结果
- 优化JOIN操作:使用合适的JOIN类型和顺序
- 避免使用ORDER BY RAND():会导致全表扫描
- 使用LIMIT子句:限制返回结果数量
- 合理设置tmp_table_size:避免临时表溢出到磁盘
5.3 常见问题与解决方案
- 查询执行时间过长:优化索引、重写SQL、增加硬件资源
- 内存不足:调整缓冲区大小、优化查询
- 临时表溢出:增加tmp_table_size和max_heap_table_size
- 锁争用:使用合适的隔离级别、减少事务大小
- 数据不一致:确保报表数据的实时性和准确性
# 查看慢查询日志
MariaDB [(none)]> SHOW VARIABLES LIKE ‘slow_query_log’;
+—————-+——-+
| Variable_name | Value |
+—————-+——-+
| slow_query_log | ON |
+—————-+——-+
# 查看慢查询阈值
MariaDB [(none)]> SHOW VARIABLES LIKE ‘long_query_time’;
+—————–+———-+
| Variable_name | Value |
+—————–+———-+
| long_query_time | 1.000000 |
+—————–+———-+
MariaDB [(none)]> SHOW VARIABLES LIKE ‘slow_query_log’;
+—————-+——-+
| Variable_name | Value |
+—————-+——-+
| slow_query_log | ON |
+—————-+——-+
# 查看慢查询阈值
MariaDB [(none)]> SHOW VARIABLES LIKE ‘long_query_time’;
+—————–+———-+
| Variable_name | Value |
+—————–+———-+
| long_query_time | 1.000000 |
+—————–+———-+
通过以上措施,可以有效提高MariaDB复杂报表SQL的开发效率和执行性能,为企业决策提供及时、准确的数据支持。
from MariaDB视频:www.itpux.com
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
