索引怎样设置,执行sql防止结果集过大,窗口函数
索引怎样设置更好?
- 选择合适字段建索引:对经常用于
WHERE子句、JOIN子句的字段建索引。比如查询语句SELECT * FROM users WHERE age = 30;,可在age字段建索引。 - 前缀索引:对长字符串字段,使用前缀索引能节省空间且保持一定查询效率,如
CREATE INDEX idx_name ON table_name (long_string_field(10));取前 10 个字符建索引。 - 组合索引:将多个字段组合成一个索引,要注意字段顺序,把选择性高(唯一值多)的字段放前面。例如
CREATE INDEX idx_user_info ON users (city, age);,查询WHERE city = 'Beijing' AND age = 30;时能有效利用索引。 - 避免冗余和重复索引:冗余索引指能由其他索引完全替代的索引,重复索引是对同一列或列组合多次建索引,应删除这类索引以节省空间和维护成本。
explain 官网解答
在 MySQL 官网(https://dev.mysql.com/doc/refman/8.0/en/using-explain.html ),
EXPLAIN用于分析 SQL 语句执行计划。它能展示查询时表的读取顺序、使用索引等信息,帮你了解查询性能瓶颈。例如执行EXPLAIN SELECT * FROM users WHERE age = 30;,可查看key列确认是否使用了age字段索引。java在执行sql时,如何一条一条返回,防止结果集过大?
在 Java 中使用 JDBC 操作 MySQL 时,要实现一条一条返回结果,防止结果集过大,可按以下方法:
使用 ResultSet 的游标特性
- 设置
ResultSet类型:在获取Statement或PreparedStatement后,通过特定的方法创建ResultSet,并将其类型设置为可滚动且只读。示例代码如下:
java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class ResultSetExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/yourdatabase";
String user = "yourusername";
String password = "yourpassword";
try (Connection conn = DriverManager.getConnection(url, user, password)) {
// 创建可滚动且只读的 Statement
String sql = "SELECT * FROM your_table";
PreparedStatement pstmt = conn.prepareStatement(sql,
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
// 处理每一条记录
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.println("ID: " + id + ", Name: " + name);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
这里
ResultSet.TYPE_SCROLL_INSENSITIVE 表示结果集可前后滚动,并且不受其他事务或语句对数据库修改的影响;ResultSet.CONCUR_READ_ONLY 表示结果集只读。使用流处理(JDBC 2.0 及以上)
- 使用
Statement或PreparedStatement:以PreparedStatement为例,执行查询后获取ResultSet,然后通过ResultSet的getRow()方法按行处理数据。
java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class StreamResultSetExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/yourdatabase";
String user = "yourusername";
String password = "yourpassword";
try (Connection conn = DriverManager.getConnection(url, user, password)) {
String sql = "SELECT * FROM your_table";
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
// 处理每一行数据
// 例如打印特定列的值
System.out.println(rs.getString("column_name"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
通过上述方式,每次只从数据库读取一条记录到内存中进行处理,避免因结果集过大导致内存溢出等问题。
什么是窗口函数?举例详细说明
窗口函数是 MySQL 8.0 引入的强大功能,它能在查询结果集的 “窗口” 内进行计算,而不改变结果集行数。“窗口” 可以是整个结果集或按某些条件划分的子集。
1. 语法结构
sql
<窗口函数> OVER (
[PARTITION BY <列清单>]
[ORDER BY <排序列清单>]
[ROWS BETWEEN <窗口范围开始> AND <窗口范围结束>]
)
- 窗口函数:像
SUM、AVG、RANK等聚合或分析函数。 - PARTITION BY:可选,用于按指定列划分数据窗口。
- ORDER BY:可选,决定窗口内数据的排序。
- ROWS BETWEEN:可选,定义窗口范围。
2. 示例数据
假设有一张
sales 表,记录不同地区不同月份的销售额:sql
CREATE TABLE sales (
region VARCHAR(50),
month INT,
amount DECIMAL(10, 2)
);
INSERT INTO sales (region, month, amount) VALUES
('North', 1, 1000.00),
('North', 2, 1500.00),
('South', 1, 800.00),
('South', 2, 900.00);
3. 聚合窗口函数示例
计算每个地区每月销售额的累计总和:
sql
SELECT
region,
month,
amount,
SUM(amount) OVER (PARTITION BY region ORDER BY month) AS running_total
FROM
sales;
PARTITION BY region:按地区划分窗口。ORDER BY month:在每个地区内按月份排序。SUM(amount) OVER (...):计算每个窗口内销售额的累计总和。
结果:
| region | month | amount | running_total |
|---|---|---|---|
| North | 1 | 1000.00 | 1000.00 |
| North | 2 | 1500.00 | 2500.00 |
| South | 1 | 800.00 | 800.00 |
| South | 2 | 900.00 | 1700.00 |
4. 分析窗口函数示例
为每个地区的每月销售额排名:
sql
SELECT
region,
month,
amount,
RANK() OVER (PARTITION BY region ORDER BY amount DESC) AS sales_rank
FROM
sales;
RANK():分析函数,用于排名。PARTITION BY region:按地区划分窗口。ORDER BY amount DESC:在每个地区内按销售额降序排序。
结果:
| region | month | amount | sales_rank |
|---|---|---|---|
| North | 2 | 1500.00 | 1 |
| North | 1 | 1000.00 | 2 |
| South | 2 | 900.00 | 1 |
| South | 1 | 800.00 | 2 |
摘抄自网络,便于检索查找。

浙公网安备 33010602011771号