(12/100)

学习思路如下:

面试准备思路

四、JDBC编程—题目

1、SQL基础
1、写SQL:找出每个城市的最新一条记录。
2、一个学生表,一个课程成绩表,怎么找出学生课程的最高分数。
3、有一组合索引(A,B,C),会出现哪几种查询方式?tag:sql语句。

2、JDBC基础
1、数据库水平切分,垂直切分。
2、数据库索引介绍一下。介绍一下什么时候用Innodb什么时候用MyISAM。
3、数据库两种引擎。
4、索引了解嘛,底层怎么实现的,什么时候会失效。
5、问了数据库的隔离级别。
6、数据库乐观锁和悲观锁。
7、数据库的三范式?
8、讲一下数据库ACID的特性?
9、mysql主从复制?
10、leftjoin和rightjoin的区别?
11、数据库优化方法。
12、谈一下你对继承映射的理解。
13、说出数据连接池的工作机制是什么?
14、事务的ACID是指什么?
15、JDBC中如何进行事务处理?

3、JDBC进阶
1、JDBC的反射,反射都是什么?
2、Jdo是什么?
3、Statement和PreparedStatement有什么区别?哪个性能更好?
4、使用JDBC操作数据库时,如何提升读取数据的性能?如何提升更新数据的性能?


答案部分:1)SQL基础

参考—https://blog.csdn.net/qq_38977097/article/details/88853266

1、写SQL:找出每个城市的最新一条记录。

答:
数据库表

select * from info as info1
join (select city ,max(createtime) as createtime from info group by city) as info2
on info1.createtime=info2.createtime and info1.city=info2.city

结果

2、一个学生表,一个课程成绩表,怎么找出学生课程的最高分数。

答:

  • 学生表(child):id ,student(姓名);
  • 成绩表(grade):id,grade,childid;
    语句: select c.student,MAX(g.grade) from grade g,child c where c.id=g.childid group by c.id;
    返回每个学生的最高成绩;

3、有一组合索引(A,B,C),会出现哪几种查询方式?tag:sql语句。

答:组合索引最左原则,有A,AB,ABC三种组合。



答案部分:2)JDBC基础

1、数据库水平切分,垂直切分。

答:当我们使用读写分离、缓存后,数据库的压力还是很大的时候,这就需要使用到数据库拆分了。
数据库拆分简单来说,就是指通过某种特定的条件,按照某个维度,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面以达到分散单库(主机)负载的效果。

切分模式: 垂直(纵向)拆分、水平拆分。

  • 垂直拆分
    专库专用,一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力分担到不同的库上面。
  • 水平拆分
    垂直拆分后遇到单机瓶颈,可以使用水平拆分。相对于垂直拆分的区别是:垂直拆分是把不同的表拆到不同的数据库中,而水平拆分是把同一个表拆到不同的数据库中。

相对于垂直拆分,水平拆分不是将表的数据做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中 的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中,主要有分表,分库两种模式。

2、数据库索引介绍一下。介绍一下什么时候用Innodb什么时候用MyISAM。

答:MyISAM和InnoDB是MySQL提供的两种搜索引擎。

  • 区别:
  • ①InnoDB支持事务与外键和行级锁,MyISAM不支持(最主要的差别)
  • ②MyISAM读性能要优于InnoDB,除了针对索引的update操作,MyISAM的写性能可能低于InnoDB,其他操作MyISAM的写性能也是优于InnoDB的,而且可以通过分库分表来提高MyISAM写操作的速度
  • ③MyISAM的索引和数据是分开的,而且索引是压缩的,而InnoDB的索引和数据是紧密捆绑的,没有使用压缩,所以InnoDB的体积比MyISAM庞大

    1)MyISAM引擎索引结构的叶子节点的数据域,存放的并不是实际的数据记录,而是数据记录的地址。索引文件与数据文件分离,这样的索引称为“非聚簇索引”。其检索算法:先按照B+Tree的检索算法检索,找到指定关键字,则取出对应数据域的值,作为地址取出数据记录。

    2)InnoDB引擎索引结构的叶子节点的数据域,存放的就是实际的数据记录。这样的索引被称为“聚簇索引”,一个表只能有一个聚簇索引。
  • ④InnoDB 中不保存表的具体行数,也就是说,执行select count() from table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count()语句包含 where条件时,两种表的操作是一样的。
  • ⑤DELETE FROM table时,InnoDB不会重新建立表,而是一行一行删除。
  • ⑥InnoDB表的行锁也不是绝对的,假如在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update table set num=1 where name like “%aaa%”
    在where条件没有主键时,InnoDB照样会锁全表。

4、索引了解嘛,底层怎么实现的,什么时候会失效?

答:MySQL官方对索引的定义为——索引(Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。

我们知道,数据库查询是数据库的最主要功能之一。我们都希望查询数据的速度能尽可能的快,因此数据库系统的设计者会从查询算法的角度进行优化。最基本的查询算法当然是顺序查找(linear search),这种复杂度为O(n)的算法在数据量很大时显然是糟糕的,好在计算机科学的发展提供了很多更优秀的查找算法,例如二分查找(binary search)、二叉树查找(binary tree search)等。如果稍微分析一下会发现,每种查找算法都只能应用于特定的数据结构之上,例如二分查找要求被检索数据有序,而二叉树查找只能应用于二叉查找树上,但是数据本身的组织结构不可能完全满足各种数据结构(例如,理论上不可能同时将两列都按顺序进行组织),所以,在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。

  • 索引并不是时时都会生效的,比如以下几种情况,将导致索引失效:
    1)如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
    注意: 要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
    2)对于多列索引,不是使用的第一部分,则不会使用索引
    3)like查询是以%开头
    4)如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引
    5)如果mysql估计使用全表扫描要比使用索引快,则不使用索引

5、数据库的隔离级别。

答:由低到高依次为Read uncommitted(未授权读取、读未提交)、Read committed(授权读取、读提交)、Repeatable read(可重复读取)、Serializable(序列化),这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。

  • (1)Read uncommitted(未授权读取、读未提交):
    1)其他事务读未提交数据,出现脏读;
    2)如果一个事务已经开始写数据,则另外一个事务则不允许同时进行写操作,但允许其他事务读此行数据。该隔离级别可以通过“排他写锁”实现。
    3)避免了更新丢失,却可能出现脏读。也就是说事务B读取到了事务A未提交的数据。
    (读未提交:一个事务写数据时,只允许其他事务对这行数据进行读,所以会出现脏读,事务T1读取T2未提交的数据)
  • (2)Read committed(授权读取、读提交):
    1)允许写事务,所以会出现不可重复读
    2)读取数据的事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。
    3)该隔离级别避免了脏读,但是却可能出现不可重复读。事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
    (读已提交:读取数据的事务允许其他事务进行操作,避免了脏读,但是会出现不可重复读,事务T1读取数据,T2紧接着更新数据并提交数据,事务T1再次读取数据的时候,和第一次读的不一样。即虚读)
  • (3)Repeatable read(可重复读取):
    1)禁止写事务;
    2)读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。
    3)避免了不可重复读取和脏读,但是有时可能出现幻读。这可以通过“共享读锁”和“排他写锁”实现。
    (可重复读:读事务会禁止所有的写事务,但是允许读事务,避免了不可重复读和脏读,但是会出现幻读,即第二次查询数据时会包含第一次查询中未出现的数据)
  • (4)Serializable(序列化):
    1)禁止任何事务,一个一个进行;
    2)提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。
    3)序列化是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻读。

6、数据库乐观锁和悲观锁。

答:

  • 悲观锁:
    总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。

  • 乐观锁:
    总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。

  • 两种锁的使用场景:
    从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。

7、数据库的三范式?

答:

  • 第一范式(1NF):原子性 字段不可再分,否则就不是关系数据库;
  • 第二范式(2NF):唯一性 一个表只说明一个事物;
  • 第三范式(3NF):每列都与主键有直接关系,不存在传递依赖;

8、讲一下数据库ACID的特性?

答:

  • 原子性(atomicity): 一个事物必须被视为一个不可分割的最小工作单元,整个事物中的操作要么全部提交成功,要么全部失败回滚,对于一个事物来说,不可能只执行其中的一部分操作,这就是的原子性。
  • 一致性(consistency): 数据库总是从一个一致性的状态转到另一个事务的一致性状态。 由于事物的一致性,所以如果这时候执行完第三系统突然奔溃,支票账户也不会损失100,因为事物还没提交
    eg:
    1)start transaction ;
    2)select * from checking where id=1;
    3)update checking set balance=balance-100 where id=1;
    4)update savings set balance=balance+100 where id=1;
    5)commit;
  • 隔离性(isolation): 一个事物所做的修改在最终提交前,对其他事物是不可见的。在前面的例子中,如果执行到第3,此时有另一个账户汇款,则其看见的支票账户得余额并没有被减去100。
  • 持久性(durability): 一旦事物提交,则其所做的修改就会永远保存在数据库中。

9、mysql主从复制?

答:前提条件:开启二进制日志,已配置主从数据库。
mysql的主从同步是基于二进制日志:
1)首先,主库会把其的数据更改(DDL DML DCL)记录到二进制日志Binary Log中。
2)接着,从库I/O线程将主库上的二进制日志复制到自己的中继日志Relay Log中。
3)最后,从库的sql线程会读取中继日志中的事件,将其重放(重新执行)在备库数据库之上,使其数据与主库一致。

10、leftjoin和rightjoin的区别?

答:
1)inner join(内连接): 在两张表进行连接查询时,只保留两张表中完全匹配的结果集。
2)left join(左连接): 在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记录。
3)right join(右连接): 在两张表进行连接查询时,会返回右表所有的行,即使在左表中没有匹配的记录。
4)full join(全连接): 在两张表进行连接查询时,返回左表和右表中所有没有匹配的行。

11、数据库优化方法。

答:
1)创建索引:
对于查询占主要的应用来说,索引显得尤为重要。很多时候性能问题很简单的就是因为我们忘了添加索引而造成的,或者说没有添加更为有效的索引导致。如果不加索引的话,那么查找任何哪怕只是一条特定的数据都会进行一次全表扫描,如果一张表的数据量很大而符合条件的结果又很少,那么不加索引会引起致命的性能下降。但是也不是什么情况都非得建索引不可,比如性别可能就只有两个值,建索引不仅没什么优势,还会影响到更新速度,这被称为过度索引。

2)复合索引:
如有有一条语句:select * from users where area=‘beijing’ and age=22;
如果我们是在area和age上分别创建单个索引的话,由于mysql查询每次只能使用一个索引,所以虽然这样已经相对不做索引时全表扫描提高了很多效率,但是如果在area、age两列上创建复合索引的话将带来更高的效率。如果我们创建了(area, age, salary)的复合索引,那么其实相当于创建了(area,age,salary)、(area,age)、(area)三个索引,这被称为最佳左前缀特性。因此我们在创建复合索引时应该将最常用作限制条件的列放在最左边,依次递减。

3)索引不会包含有NULL值的列:
只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为NULL。

4)使用短索引:
对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个CHAR(255)的 列,如果在前10 个或20 个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

5)排序的索引问题:
mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。

6)like语句操作:
一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。

7)不要在列上进行运算:
select * from users where YEAR(adddate)<2007;
将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成select * from users where adddate<‘2007-01-01’;

8)不使用NOT IN和<>操作:
NOT IN和<>操作都不会使用索引将进行全表扫描。NOT IN可以NOT EXISTS代替,id<>3则可使用id>3 or id<3来代替。

12、谈一下你对继承映射的理解。

答:继承关系的映射策略有三种:
① 每个继承结构一张表(table per class hierarchy),不管多少个子类都用一张表。
② 每个子类一张表(table per subclass),公共信息放一张表,特有信息放单独的表。
③ 每个具体类一张表(table per concrete class),有多少个子类就有多少张表。
第一种方式属于单表策略,其优点在于查询子类对象的时候无需表连接,查询速度快,适合多态查询;缺点是可能导致表很大。后两种方式属于多表策略,其优点在于数据存储紧凑,其缺点是需要进行连接查询,不适合多态查询。

13、说出数据连接池的工作机制是什么?

答:

  • 工作机制: 数据库连接池在初始化时,将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。

  • 数据库连接池的最小连接数最大连接数的设置要考虑到下列几个因素:
    1)最小连接数是连接池一直保持的数据库连接,如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费;
    2)最大连接数是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求将被加入到等待队列中,这会影响之后的数据库操作。
    3)如果最小连接数与最大连接数相差太大,那么最先的连接请求将会获利,之后超过最小连接数量的连接请求等价于建立一个新的数据库连接。这些大于最小连接数的数据库连接在使用完不会马上被释放,它将被放到连接池中等待重复使用或是空闲超时后被释放。

14、事务的ACID是指什么?

答:

  • 原子性(atomicity): 一个事物必须被视为一个不可分割的最小工作单元,整个事物中的操作要么全部提交成功,要么全部失败回滚,对于一个事物来说,不可能只执行其中的一部分操作,这就是的原子性。
  • 一致性(consistency): 数据库总是从一个一致性的状态转到另一个事务的一致性状态。 由于事物的一致性,所以如果这时候执行完第三系统突然奔溃,支票账户也不会损失100,因为事物还没提交
    eg:
    1)start transaction ;
    2)select * from checking where id=1;
    3)update checking set balance=balance-100 where id=1;
    4)update savings set balance=balance+100 where id=1;
    5)commit;
  • 隔离性(isolation): 一个事物所做的修改在最终提交前,对其他事物是不可见的。在前面的例子中,如果执行到第3,此时有另一个账户汇款,则其看见的支票账户得余额并没有被减去100。
  • 持久性(durability): 一旦事物提交,则其所做的修改就会永远保存在数据库中。

15、JDBC中如何进行事务处理?

答:connect. setAutocommit commit rollback
Connection提供了事务处理的方法,通过调用setAutoCommit(false)可以设置手动提交事务;当事务完成后用commit()显式提交事务;如果在事务处理过程中发生异常则通过rollback()进行事务回滚。除此之外,从JDBC 3.0中还引入了Savepoint(保存点)的概念,允许通过代码设置保存点并让事务回滚到指定的保存点。
事务



答案部分:3)JDBC进阶

1、JDBC的反射,反射都是什么?

答:

  • 什么是JDBC?
    Java定义了一套关于连接使用数据库的规范(接口)叫做JDBC,许多数据库厂商实现了这个规范,所以我们可以通过Java提供的接口编程,使得我们更换数据库的时候不用修改原来的代码,只需要通过修改配置文件即可,修改什么配置文件呢?下面会说。
  • 什么是反射?
    如果我们在程序运行的时候得到一个字符串,而这个字符串是某个类的类名,如果要实例化这个类,那么就需要用到反射。
String className = "com.mysql.jdbc.Driver";//完整的包名+类名
Driver driver = (Driver)Class.forName(driverClass).newInstance();//通过反射实例化这个类
  • JDBC的使用过程:

1)首先通过反射com.mysql.jdbc.Driver类,实例化该类的时候会执行该类内部的静态代码块,该代码块会在Java实现的DriverManager类中注册自己,DriverManager管理所有已经注册的驱动类,当调用DriverManager.geConnection方法时会遍历这些驱动类,并尝试去连接数据库,只要有一个能连接成功,就返回Connection对象,否则则报异常。

2)通过使用DriverManager.geConnection(url,user,password)函数,传入url,数据库用户名,数据库密码,得到数据库的Connection对象。com.mysql.jdbc.Driver是mysql驱动类的全名,oracle驱动类的全名是oracle.jdbc.driver.OracleDriver。

  • 连接数据库时要传入相应的url,
mysql url的格式是:jdbc:mysql://<ip>:3306/<database_name>
oracle url的格式是:jdbc:oracle:thin:<ip>:1521:<database_name>

2、Jdo是什么?

答:
JDO是Java对象持久化的新的规范,为java data object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储,因此对开发人员来说,存储数据对象完全不需要额外的代码(如JDBC API的使用)。这些繁琐的例行工作已经转移到JDO产品提供商身上,使开发人员解脱出来,从而集中时间和精力在业务逻辑上。另外,JDO很灵活,因为它可以在任何数据底层上运行。JDBC只是面向关系数据库(RDBMS)JDO更通用,提供到任何数据底层的存储功能,比如关系数据库、文件、XML以及对象数据库(ODBMS)等等,使得应用可移植性更强。

3、Statement和PreparedStatement有什么区别?哪个性能更好?

答:与Statement相比:

  • ①PreparedStatement接口代表预编译的语句,它主要的优势在于可以减少SQL的编译错误并增加SQL的安全性
    (减少SQL注射攻击的可能性);
  • ②PreparedStatement中的SQL语句是可以带参数的,避免了用字符串连接拼接SQL语句的麻烦和不安全;
  • ③当批量处理SQL或频繁执行相同的查询时,PreparedStatement有明显的性能上的优势,由于数据库可以将编译优化后的SQL语句缓存起来,下次执行相同结构的语句时就会很快(不用再次编译和生成执行计划);

4、使用JDBC操作数据库时,如何提升读取数据的性能?如何提升更新数据的性能?

答:

  • 要提升读取数据的性能,可以指定通过结果集(ResultSet)对象的setFetchSize()方法指定每次抓取的记录数(空间换时间策略);
  • 要提升更新数据的性能,可以使用PreparedStatement语句构建批处理,将若干SQL语句置于一个批处理中执行。

第12天(1/1)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值