Comparison between class serialized storage and class native storage

Comparison between class serialized storage and class native storage

 

        Java serialization is to convert an object into a string of binary byte arrays, and achieve the purpose of persistence by saving or transferring these byte data. The essence of serialization is to save the current state information of the object, and there is no need to save the complete structural information.

        The native storage of Java classes is to map objects to the relationship of the database. An entity class corresponds to a table in the database, and member variables in the class correspond to fields in the database. The purpose of data persistence is achieved through the container of the database.

Both of the above two methods can achieve the purpose of data persistence, so is there any difference in performance between the two?

        We will use a comparative experiment to verify whether there is a difference in performance between the two, design a Student class with 12 attributes and implement a serializable interface, and design its corresponding database table and table for storing its serialization, respectively. Observe the difference in time efficiency and space efficiency between the two during the process of accessing records from the database.

Student class that implements serialization interface


import java.io.Serializable;
import java.util.Date;

/*
 * 实现可序列化接口
 */
public class Student implements Serializable{
    private Integer id;

    private String name;

    private int age;

    private int gender;

    private String dept;

    private String tel;

    private String email;

    private String hobby;

    private String school;

    private double wallet;

    private int zodiac;

    private String address;

    public Student() {
    }

    public Student(Integer id, String name, int age, int gender, String dept, String tel, String email, String hobby, String school, double wallet, int zodiac, String address) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.dept = dept;
        this.tel = tel;
        this.email = email;
        this.hobby = hobby;
        this.school = school;
        this.wallet = wallet;
        this.zodiac = zodiac;
        this.address = address;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getGender() {
        return gender;
    }

    public void setGender(int gender) {
        this.gender = gender;
    }

    public String getDept() {
        return dept;
    }

    public void setDept(String dept) {
        this.dept = dept;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }

    public String getSchool() {
        return school;
    }

    public void setSchool(String school) {
        this.school = school;
    }

    public double getWallet() {
        return wallet;
    }

    public void setWallet(double wallet) {
        this.wallet = wallet;
    }

    public int getZodiac() {
        return zodiac;
    }

    public void setZodiac(int zodiac) {
        this.zodiac = zodiac;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                ", dept='" + dept + '\'' +
                ", tel='" + tel + '\'' +
                ", email='" + email + '\'' +
                ", hobby='" + hobby + '\'' +
                ", school='" + school + '\'' +
                ", wallet=" + wallet +
                ", zodiac=" + zodiac +
                ", address='" + address + '\'' +
                '}';
    }
}

Student table structure for storing entity classes

create table if not exists student (
	id int primary key,
	name varchar(10),
	age int,
	gender int,
	dept varchar(10) not null,
	tel varchar(11) unique,
	email varchar(18) unique,
	hobby varchar(10),
	school varchar(10) not null,
	wallet double(10,2),
	zodiac int,
	address varchar(20)
);

Store serialized objtest table structure

create table if not exists objtest(
    id int primary key,
    obj blob not null
);

        

        Design the DBHelper class to implement the operation of the database connection pool. Its functions include data connection pool configuration, recycling, database table insertion, database table query, database table emptying, and returning the space occupied by the table in memory.

        

DBHelper class

        Database connection pool configuration

public class DBHelper {
    private static Connection conn;
    private static PreparedStatement pres;
    private static ResultSet rs;
    private static ResourceBundle bundle = ResourceBundle.getBundle("jdbc");

    static {
        try {
            Class.forName(bundle.getString("Driver"));
            String url = bundle.getString("url");
            String user = bundle.getString("user");
            String password = bundle.getString("password");

            conn = DriverManager.getConnection(url, user, password);
            if (conn != null) {
                System.out.println("数据库连接成功");
            } else System.out.println("数据库连接失败");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

        Database connection pool recycling

public static void free(Connection conn, PreparedStatement pres, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (pres != null) {
            try {
                pres.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }

        Student object serialized storage

public static void save(List<Student> students){
        long startTime = System.currentTimeMillis();
        String sql = "insert into objtest(obj) values(?)";
        try {
            pres=conn.prepareStatement(sql);
            for(int i = 0; i < students.size(); i ++){
                pres.setObject(1, students.get(i));
                pres.addBatch();
            }
            pres.executeBatch();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            free(conn, pres, null);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("序列化存储运行时间:" + (endTime - startTime));
    }

        Student object serialization query, deserialization

public static List<Student> read(){
        long startTime = System.currentTimeMillis();
        List<Student> list = new ArrayList<Student>();
        String sql="select obj from objtest";

        try {
            pres = conn.prepareStatement(sql);

            rs = pres.executeQuery();
            while(rs.next()){

                Blob blob = rs.getBlob(1);
                InputStream is = blob.getBinaryStream();
                BufferedInputStream buffer = new BufferedInputStream(is);

                byte[] buff = new byte[(int) blob.length()];
                while((buffer.read(buff, 0, buff.length)) != -1) {
                    ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(buff));
                    Student student = (Student) in.readObject();
                    list.add(student);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            free(conn, pres, rs);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("序列化读取运行时间:" + (endTime - startTime));
        return list;
    }

        Student object native storage

public static void saveStudent(List<Student> students) {
        long startTime = System.currentTimeMillis();
        String sql = "insert into student(id, name, age, gender, dept, tel, email, hobby, school, wallet, zodiac, address) values (?,?,?,?,?,?,?,?,?,?,?,?)";
        try {
            pres = conn.prepareStatement(sql);
            for (Student student : students) {
                pres.setInt(1, student.getId());
                pres.setString(2, student.getName());
                pres.setInt(3, student.getAge());
                pres.setInt(4, student.getGender());
                pres.setString(5, student.getDept());
                pres.setString(6, student.getTel());
                pres.setString(7, student.getEmail());
                pres.setString(8, student.getHobby());
                pres.setString(9, student.getSchool());
                pres.setDouble(10, student.getWallet());
                pres.setInt(11, student.getZodiac());
                pres.setString(12, student.getAddress());
                pres.addBatch();
            }
            pres.executeBatch();

        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("直接存储运行时间:" + (endTime - startTime) + "ms");
    }

        Student Object Native Query

public static List<Student> readStudent() {
        long startTime = System.currentTimeMillis();
        List<Student> list = new ArrayList<Student>();
        String sql = "select * from student";

        try {
            pres = conn.prepareStatement(sql);
            rs = pres.executeQuery();
            while (rs.next()) {
                Integer id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                int gender = rs.getInt("gender");
                String dept = rs.getString("dept");
                String tel = rs.getString("tel");
                String email = rs.getString("email");
                String hobby = rs.getString("hobby");
                String school = rs.getString("school");
                double wallet = rs.getDouble("wallet");
                int zodiac = rs.getInt("zodiac");
                String address = rs.getString("address");
                Student student = new Student(id, name, age, gender, dept, tel, email, hobby, school, wallet, zodiac, address);
                list.add(student);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("直接读取运行时间:" + (endTime - startTime) + "ms");
        return list;
    }

        Clear the database table

public static void cleanTable() {
        String sql1 = "truncate table student";
        String sql2 = "truncate table objtest";
        try {
            pres = conn.prepareStatement(sql1);
            pres.executeUpdate();
            pres = conn.prepareStatement(sql2);
            pres.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            free(conn, pres, null);
        }
    }

        Memory space occupied by query records

public static void getMemory(String tableName) {
        double memory = 0;
        int rows = 0;
        String sql = "SELECT TABLE_NAME,DATA_LENGTH+INDEX_LENGTH memory,TABLE_ROWS FROM TABLES WHERE TABLE_SCHEMA='jdbc' AND TABLE_NAME=?";
        try {
            pres = conn.prepareStatement(sql);
            pres.setString(1, tableName);
            rs = pres.executeQuery();
            if (rs.next()) {
                memory = rs.getDouble("memory");
                rows = rs.getInt("TABLE_ROWS");
            }
            System.out.println("表中记录数: " + rows + " 占用内存空间:" + memory / 1024 + "KB");
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

        

experiment procedure

        Design the Test test class to repeatedly insert and query the student entity classes with different numbers of records, and conduct a control experiment by observing the time stamps consumed in the process of storing and querying in the database.

        

Experimental sample

        Set the number of records in five groups as 1, 5, 200, 1000, 5000, and 10,000, repeat the storage and query 5 times, and take the average value of the running time and memory space.

        

        Test class

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int count = scanner.nextInt();
        List<Student> list = new ArrayList<>();
        DBHelper.cleanTable(); // 清空数据库表
        for (int i = 1; i <= count; i++) {
            list.add(new Student(i, "zhangsan", 18, 1, "计算机系", "10086", "[email protected]", "basketball", "温州大学", 3.8, 5, "温州大学计算机与人工智能学院"));
        }
        System.out.println("记录数为 "+ count +"条时:");
        DBHelper.save(list); // 学生类序列化存储
        DBHelper.saveStudent(list); // 学生类对象存储
        DBHelper.read(); // 学生类序列化查询
        DBHelper.readStudent(); // 学生类对象查询
    }
}

        

Experimental results 

Storing data
Number of records/article Native (average time/ms) Serialization (average time/ms)
1 10.8 27.2
200 666.4 734.2
1000 3038.4 3211.8
5000 14080.8 14384.2
10000 27909.4 28020.4
Query data
Number of records/article Native (average time/ms) Serialization (average time/ms)
1 4.6 24.0
200 48.2 95.0
1000 120.2 195.6
5000 226.0 440.6
10000 320.4 759.4

memory space
Number of records/article Native (memory size/kb) Serialization (memory size/kb)
1 16 16
200 64 64
1000 192 496
5000 1552 2576
10000 2576 5648

           Through experiments, it is found that the storage time of the serialized data is similar to that of the original storage as the number of records increases, but the time spent in the query process is about twice that of the original query; in terms of memory space, with the As the number of records increases, the memory occupied by the serialized data also increases. It can be seen that for the persistent storage of entity objects, native storage performs better in efficiency than serialized storage.

        The possible reasons for the difference in serialization efficiency are:

        1. It takes a certain amount of time to serialize and deserialize the class itself;

        2. The serialized data is a binary stream, which occupies a larger space (about 412bytes/item), and consumes more time during database query and cross-domain return after query.

 personal opinion

        For the two persistent storage methods, it is clearer to directly use the mapping between entity classes and database tables, which is convenient for performing various query, modification and deletion operations, and can easily obtain the required query conditions; in terms of data security, no The mapping of the encrypted entity class on the database table will be displayed in the form of plain text, and a set of incomprehensible byte streams obtained through serialization of the object, but it can still be deserialized and restored to the original state in the JVM environment. There is form. However, in inter-process communication, object transfer between processes is realized, and the byte stream generated after serialization can show the characteristics of high efficiency, convenience, and durability during transmission.

 reference article

(45 messages) After the MySQL8 version, the number of rows in the system table information_schema.tables and the number of rows in the actual data table are inaccurately handled_AllenLeungX's Blog-CSDN Blog

Guess you like

Origin blog.csdn.net/qq_43500084/article/details/127639090