索引怎样设置,执行sql防止结果集过大,窗口函数

索引怎样设置更好?
 
  1. 选择合适字段建索引:对经常用于 WHERE 子句、JOIN 子句的字段建索引。比如查询语句SELECT * FROM users WHERE age = 30;,可在 age 字段建索引。
  2. 前缀索引:对长字符串字段,使用前缀索引能节省空间且保持一定查询效率,如CREATE INDEX idx_name ON table_name (long_string_field(10)); 取前 10 个字符建索引。
  3. 组合索引:将多个字段组合成一个索引,要注意字段顺序,把选择性高(唯一值多)的字段放前面。例如CREATE INDEX idx_user_info ON users (city, age);,查询WHERE city = 'Beijing' AND age = 30; 时能有效利用索引。
  4. 避免冗余和重复索引:冗余索引指能由其他索引完全替代的索引,重复索引是对同一列或列组合多次建索引,应删除这类索引以节省空间和维护成本。

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 的游标特性

  1. 设置 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 及以上)

  1. 使用 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 <窗口范围结束>]
)
 

  • 窗口函数:像 SUMAVGRANK 等聚合或分析函数。
  • 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
 
 
posted @ 2025-05-08 14:54  CharyGao  阅读(18)  评论(0)    收藏  举报