当前位置: 首页 > 工具软件 > SimpleDB > 使用案例 >

数据库系统-SimpleDB

祁修平
2023-12-01


数据库系统

    数据库是存储在计算机上的数据的集合。数据库中的数据通常被组织成记录,如员工记录、医疗记录、销售记录等。
   数据库五个最基本要求:

  1. 数据库必须是持久的。否则,一旦计算机被关闭,这些记录就会消失。
  2. 数据库可以共享。许多数据库旨在由多个并发用户共享。
  3. 数据库必须保持准确。如果用户不能信任数据库的内容,那么它就会变得毫无价值。
  4. 数据库存储量可以非常大。一个数据库包含数百万条(甚至数十亿条)的记录并不罕见。
  5. 数据库必须可用。如果用户不能轻易获得他们想要的数据,他们的生产力将受到影响,他们会呼吁另一个不同的产品。
    ​ 每个数据库需求都迫使数据库系统包含越来越多的特性,从而导致数据库系统比预期的更复杂。

数据存储

   使数据库持久化的一种常见方法是将其记录存储在文件中。最简单和最直接的方法是让数据库系统将记录存储在文本文件中,每个记录类型有一个文件;每条记录都可以是一行文本,其值用分隔符分隔。
   这种方法的优点是,用户可以使用文本编辑器来检查和修改文件。但是这种方法效率太低以至于不建议采用。缺点在于:大型文本文件花费的读写时间太长。
   因此,数据库系统需要更加聪明地了解如何存储记录(例如建立索引[index]),因此对文件的更新只需要很小的本地重写。

多用户连接(并发)

   当许多用户共享一个数据库时,他们很有可能同时访问数据库的一些数据文件。并发是一件好事,因为每个用户都可以快速得到服务,而无需等待其他用户完成服务。但是并发过度会导致数据库变得不准确。解决这个问题的一个方法是限制并发度。用户还可能需要撤销他们所做的数据库更新。
    数据库系统必须为用户提供指定更改何时永久的能力;用户提交更改。一旦用户提交,更改就会变得可见,无法撤消。

数据恢复

   实现数据库系统从崩溃中正常恢复,从而撤销在崩溃发生时正在运行的所有程序的更新。

内存管理

   数据库系统面临着以下难题:它必须管理比主内存系统更多的数据,使用较慢的设备,多个人争夺访问数据,并使其完全恢复,同时保持合理的响应时间。
   解决这个难题的很大一部分是使用缓存。每当数据库系统需要处理一条记录时,它就会将其加载到RAM中,并尽可能长时间地保存在那里。因此,主内存将包含当前正在使用的数据库的那部分。所有的读写都是用RAM进行的。这种策略的优点是使用快速主存而不是慢的持久内存,但缺点是数据库的持久版本可能会过时。数据库系统需要实现技术来保持数据库的持久版本与RAM版本同步,即使在系统崩溃(RAM内容被销毁时)也是如此。

可用性

    如果数据库的用户不能轻松地提取他们想要的数据,那么该数据库就不是很有用。SQL语句比Java程序要短得多、更清晰,这主要是因为它指定了要从文件中提取的值,而不必指定如何检索它们。

Derby数据库

   Apache Derby 是一个Apache DB 子项目,是一个完全用 Java 实现的开源关系数据库,可在Apache 许可证 2.0 版下使用。一些关键功能包括:

快速入门

Derby内嵌开发案例

   Derby内嵌开发需要引入derby.jar,以下为其中一个例子:

//创建数据库
public static void creat() {
        String url = "jdbc:derby:d:/test/studentdb;create=true";//其中d:/test/studentdb指定数据库studentdb的存储位置为d:/test/,create=true表明此连接创建数据库
        Driver d = new EmbeddedDriver();
        try (Connection conn = d.connect(url, null);
             Statement stmt = conn.createStatement()) {

            String s = "create table STUDENT(SId int, SName varchar(10), MajorId int, GradYear int)";//创建STUDENT表
            stmt.executeUpdate(s);
            System.out.println("Table STUDENT created.");

            s = "insert into STUDENT(SId, SName, MajorId, GradYear) values ";
            String[] studvals = {"(1, 'joe', 10, 2021)",
                    "(2, 'amy', 20, 2020)",
                    "(3, 'max', 10, 2022)",
                    "(4, 'sue', 20, 2022)",
                    "(5, 'bob', 30, 2020)",
                    "(6, 'kim', 20, 2020)",
                    "(7, 'art', 30, 2021)",
                    "(8, 'pat', 20, 2019)",
                    "(9, 'lee', 10, 2021)"};
            for (int i = 0; i < studvals.length; i++)
                stmt.executeUpdate(s + studvals[i]);
            System.out.println("STUDENT records inserted.");

            s = "create table DEPT(DId int, DName varchar(8))";
            stmt.executeUpdate(s);
            System.out.println("Table DEPT created.");

            s = "insert into DEPT(DId, DName) values ";
            String[] deptvals = {"(10, 'compsci')",
                    "(20, 'math')",
                    "(30, 'drama')"};
            for (int i = 0; i < deptvals.length; i++)
                stmt.executeUpdate(s + deptvals[i]);
            System.out.println("DEPT records inserted.");

            s = "create table COURSE(CId int, Title varchar(20), DeptId int)";
            stmt.executeUpdate(s);
            System.out.println("Table COURSE created.");

            s = "insert into COURSE(CId, Title, DeptId) values ";
            String[] coursevals = {"(12, 'db systems', 10)",
                    "(22, 'compilers', 10)",
                    "(32, 'calculus', 20)",
                    "(42, 'algebra', 20)",
                    "(52, 'acting', 30)",
                    "(62, 'elocution', 30)"};
            for (int i = 0; i < coursevals.length; i++)
                stmt.executeUpdate(s + coursevals[i]);
            System.out.println("COURSE records inserted.");

            s = "create table SECTION(SectId int, CourseId int, Prof varchar(8), YearOffered int)";
            stmt.executeUpdate(s);
            System.out.println("Table SECTION created.");

            s = "insert into SECTION(SectId, CourseId, Prof, YearOffered) values ";
            String[] sectvals = {"(13, 12, 'turing', 2018)",
                    "(23, 12, 'turing', 2019)",
                    "(33, 32, 'newton', 2019)",
                    "(43, 32, 'einstein', 2017)",
                    "(53, 62, 'brando', 2018)"};
            for (int i = 0; i < sectvals.length; i++)
                stmt.executeUpdate(s + sectvals[i]);
            System.out.println("SECTION records inserted.");

            s = "create table ENROLL(EId int, StudentId int, SectionId int, Grade varchar(2))";
            stmt.executeUpdate(s);
            System.out.println("Table ENROLL created.");

            s = "insert into ENROLL(EId, StudentId, SectionId, Grade) values ";
            String[] enrollvals = {"(14, 1, 13, 'A')",
                    "(24, 1, 43, 'C' )",
                    "(34, 2, 43, 'B+')",
                    "(44, 4, 33, 'B' )",
                    "(54, 4, 53, 'A' )",
                    "(64, 6, 53, 'A' )"};
            for (int i = 0; i < enrollvals.length; i++)
                stmt.executeUpdate(s + enrollvals[i]);
            System.out.println("ENROLL records inserted.");

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

​ 查询例子如下:

public static void query() {
        String url = "jdbc:derby:d:/test/studentdb";
        String qry = "select SName, DName "
                + "from DEPT, STUDENT "
                + "where MajorId = DId";

        Driver d = new EmbeddedDriver();
        try ( Connection conn = d.connect(url, null);
              Statement stmt = conn.createStatement();
              ResultSet rs = stmt.executeQuery(qry)) {
            System.out.println("Name\tMajor");
            while (rs.next()) {
                String sname = rs.getString("SName");
                String dname = rs.getString("DName");
                System.out.println(sname + "\t" + dname);
            }
        }
        catch(SQLException e) {
            e.printStackTrace();
        }
    }

数据库引擎

   数据库应用程序一般由两个独立的部分组成:用户界面(或UI)和访问数据库的代码。后一种代码被称为数据库引擎。将UI与数据库引擎分离是一个很好的系统设计,因为它简化了应用程序的开发。这种分离还增加了系统的灵活性:应用程序设计器可以对不同的数据库引擎使用相同的用户界面,或者为同一数据库引擎构建不同的用户界面。
   UI通过连接到所需的引擎,然后从引擎的API中调用方法来访问数据库。数据库引擎通常支持多个标准api。当一个Java程序连接到一个引擎时,所选择的API被称为JDBC
   从UI到数据库引擎的连接可以是嵌入式的或基于服务器的。在嵌入式连接中,数据库引擎的代码与UI的代码运行相同的过程,这允许UI对引擎的独占访问。只有当数据库“属于”该应用程序并且与该应用程序存储在同一台机器上时,该应用程序才应该使用嵌入式连接。其他应用程序也需要使用基于服务器的连接。
   在一个基于服务器的连接中,数据库引擎的代码在一个专用的服务器程序中执行。此服务器程序始终在运行,等待客户端连接,并且不需要与其客户端在同一台机器上。在客户端与服务器建立连接后,客户机向服务器发送JDBC请求并接收响应。一个服务器可以同时连接到多个客户端。当服务器正在处理一个客户端的请求时,其他客户端可以发送他们自己的请求。服务器包含一个调度程序,它将为等待服务的请求排队,并确定它们何时被执行。每个客户端都不知道其他客户端,而且(除了由于调度而造成的延迟)都有一种令人愉快的错觉,即服务器是专门处理它的。基于服务器的连接的连接字符串必须指定服务器计算机的网络或IP地址。

SimpleDB数据库

   Derby是一个复杂的、功能齐全的数据库系统。然而,这种复杂性意味着它的源代码不容易理解或修改。作者编写SimpleDB数据库系统是为了实现与Derby相反的方法——它的代码很小、易于阅读、易于修改。它省略了所有不必要的功能,只实现了SQL的一小部分,并且只使用了最简单的(通常是非常不切实际的)算法。它的目的是让读者清楚地了解数据库引擎的每个组件以及这些组件是如何交互的。
   最新版本的SimpleDB可以从其网站cs.bc.edu/~scioreb下载。

SimpleDB的SQL版本

   Derby几乎实现了几乎所有的标准SQL。而SimpleDB只实现了标准SQL的一个很小的子集,并施加了SQL标准中不存在的限制。SimpleDB中的查询只包含选择-where子句,这些子句中的选择子句包含一个字段名列表(不包含AS关键字),而from子句包含一个表名列表(不包含范围变量)。可选的where子句中的术语只能通过布尔运算符和进行连接。术语只能比较常量和字段名是否相等。与标准SQL不同,没有其他比较运算符,没有其他布尔运算符,没有算术运算符或内置函数,也没有圆括号。因此,不支持嵌套的查询、聚合和计算值。
   因为没有范围变量和重命名,所以查询中的所有字段名都必须不相交。因为没有按子句分组或顺序排序,所以不支持分组和排序。其他限制包括:

  • 不支持选择子句中的“”缩写。
  • 没有空值。
  • 在from子句中没有显式的连接或外部连接。
  • 不支持联合关键字。
  • 插入语句只接受显式值。也就是说,不能由查询指定一个插入。
  • 一个更新语句在set子句中只能有一个赋值。

小结

  1. 数据库是存储在计算机上的数据的集合。数据库中的数据通常被组织到记录中。数据库系统是一种管理数据库中的记录的软件。
  2. 数据库系统必须能够处理大型共享数据库,并将其数据持久化存储。它必须为其数据提供一个高级接口,并确保在面对相互冲突的用户更新和系统崩溃时数据的准确性。数据库系统通过以下功能满足这些要求:
    • 记录存储记录在一个文件中的能力,使用一种格式可以更有效地访问比文件系统通常允许
    • 复杂算法索引数据文件,支持快速访问,能够处理并发访问多个用户的网络,必要时阻止用户,支持提交和回滚更改
    • 将数据库记录缓存在主存中,并管理数据库持久和主存版本之间的同步,如果系统崩溃,则将数据库恢复到一个合理的状态
    • 一种语言编译器/解释器,用于将表上的用户查询转换为文件上的可执行代码
    • 查询优化策略,以便将低效的查询转换为更有效的查询
  3. 数据库引擎是维护数据的数据库系统的组件。数据库应用程序负责用户的输入和输出;它调用数据库引擎来获取它所需要的数据。
  4. 与数据库引擎的连接可以是嵌入式的,也可以是基于服务器的。具有嵌入式连接的程序具有对该数据库引擎的独占访问权限。具有基于服务器的连接的程序与其他并发程序共享该引擎。
  5. 两个基于java的数据库系统分别是Derby和SimpleDB。Derby实现了完整的SQL标准,而SimpleDB只实现了SQL的一个有限的子集。SimpleleDB很有用,因为它的代码很容易理解。

参考链接

  1. SimpleDB
  2. Derby
 类似资料: