表的连接方式介绍(NESTED LOOP, SORT MERGE JOIN, HASH JOIN )
循环嵌套链接(NESTED LOOP)
嵌套循环链接的内部处理的流程如下。
- Oracle 优化器根据基于规则RBO或基于成本CBO的原则,选择两个表中的一个作为驱动表,并指定其为外部表。
- Oracle 优化器再将另外一个表指定为内部表。
- Oracle从外部表中读取第一行,然后和内部表中的数据逐一进行对比,所有匹配的记录放在结果集中。
- Oracle读取外部表中的第二行,再和内部表中的数据逐一进行对比,所有匹配的记录添加到结果集中。
- 重复上述步骤,直到外部表中的所有记录全部处理完。
- 最后产生满足要求的结果集。
使用嵌套循环链接是一种从结果集中提取第一批记录最快速的方法。在驱动行源表(就是正在查找的记录)较小或者内部行源表已链接的列有惟一的索引或高度可选的非惟一索引时, 嵌套循环链接效果是比较理想的。嵌套循环链接比其他链接方法有优势,它可以快速地从结果集中提取第一批记录,而不用等待整个结果集完全确定下来。这样,在理想情况下,终端用户就可以通过查询屏幕查看第一批记录,而在同时读取其他记录。不管如何定义链接的条件或者模式,任何两行记录源可以使用嵌套循环链接,所以嵌套循环链接是非常灵活的。
然而,如果内部行源表(读取的第二张表)已链接的列上不包含索引或者索引不是高度可选时,嵌套循环链接效率是很低的。如果驱动表的记录非常庞大时,其他的链接方法可能更加有效。一般在nested loop中, 驱动表满足条件结果集不大,被驱动表的链接字段要有索引,这样就有nested loop。如果驱动表返回记录太多,就不适合nested loops了。如果链接字段没有索引,则适合走hash join,因为不需要索引。可以通过在SQL语句中添加HINTS,强制Oracle优化器产生嵌套循环链接的执行计划。
嵌套循环示例
被驱动表连接列创建索引
SQL> create index idx_t2 on t2(col2);
Index created.
当前数据库版本
SQL> select * from v$version;
BANNER
————————————————————————————————————————
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 – 64bit Production
PL/SQL Release 11.2.0.4.0 – Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 – Production
NLSRTL Version 11.2.0.4.0 – Production
查询方法 一
SQL> select /*+ ordered use_nl(t2)*/ t1.col1,t1.col2,t2.col3 from t1,t2 where t1.col2=t2.col2;
Execution Plan
———————————————————-
Plan hash value: 1054738919
—————————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————————
| 0 | SELECT STATEMENT | | 3 | 60 | 6 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 3 | 60 | 6 (0)| 00:00:01 |
| 2 | NESTED LOOPS | | 3 | 60 | 6 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL | T1 | 3 | 45 | 3 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | IDX_T2 | 1 | | 0 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 5 | 1 (0)| 00:00:01 |
—————————————————————————————
Predicate Information (identified by operation id):
—————————————————
4 – access("T1"."COL2"="T2"."COL2")
查询方法二
SQL> select /*+ use_nl(t1 t2)*/ t1.col1,t1.col2,t2.col3 from t1,t2 where t1.col2=t2.col2;
Execution Plan
———————————————————-
Plan hash value: 1054738919
—————————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————————
| 0 | SELECT STATEMENT | | 3 | 60 | 6 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 3 | 60 | 6 (0)| 00:00:01 |
| 2 | NESTED LOOPS | | 3 | 60 | 6 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL | T1 | 3 | 45 | 3 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | IDX_T2 | 1 | | 0 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| T2 | 1 | 5 | 1 (0)| 00:00:01 |
—————————————————————————————
Predicate Information (identified by operation id):
—————————————————
4 – access("T1"."COL2"="T2"."COL2")
排序合并链接( SORT MERGE JOIN )
排序合并链接内部处理的流程如下。
优化器判断第一个源表是否已经排序,如果已经排序,则到第3步,否则到第2步。
第一个源表排序。
优化器判断第二个源表是否已经排序,如果已经排序,则到第5步,否则到第4步。
第二个源表排序。
已经排过序的两个源表进行合并操作,并生成最终的结果集。
在缺乏数据的选择性或者可用的索引时,或者两个源表都过于庞大(所选的数据超过表记录数的5%)时,排序合并链接将比嵌套循环链接更加高效。排列合并链接需要比较大的临时内存块,以用于排序,这将导致在临时表空间占用更多的内存和磁盘I/O。
排序合并连接示例
SQL> select /*+ ordered use_merge(t2)*/ t1.col1,t1.col2,t2.col3 from t1,t2 where
t1.col2=t2.col2;
Execution Plan
———————————————————-
Plan hash value: 412793182
—————————————————————————-
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————-
| 0 | SELECT STATEMENT | | 3 | 60 | 8 (25)| 00:00:01 |
| 1 | MERGE JOIN | | 3 | 60 | 8 (25)| 00:00:01 |
| 2 | SORT JOIN | | 3 | 45 | 4 (25)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T1 | 3 | 45 | 3 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 3 | 15 | 4 (25)| 00:00:01 |
| 5 | TABLE ACCESS FULL| T2 | 3 | 15 | 3 (0)| 00:00:01 |
—————————————————————————-
Predicate Information (identified by operation id):
—————————————————
4 – access("T1"."COL2"="T2"."COL2")
filter("T1"."COL2"="T2"."COL2")
Note
—–– dynamic sampling used for this statement (level=2)
笛卡尔链接 ( CARTESIAN JOIN )
笛卡尔链接是指在SQL语句中没有写出表链接的条件,优化器把第一个表的每一条记录和第二个表的所有记录相链接。如果第一个表的记录数为m,第二个表的记录数为m,则会产生m×n条记录数。
笛卡尔链接示例
下面的查询,未指名链接条件,就会产生笛卡尔链接。
SQL> select t1.col1,t1.col2,t2.col3 from t1,t2;
9 rows selected.
Execution Plan
———————————————————-
Plan hash value: 787647388
—————————————————————————–
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————–
| 0 | SELECT STATEMENT | | 9 | 162 | 9 (0)| 00:00:01 |
| 1 | MERGE JOIN CARTESIAN| | 9 | 162 | 9 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL | T1 | 3 | 45 | 3 (0)| 00:00:01 |
| 3 | BUFFER SORT | | 3 | 9 | 6 (0)| 00:00:01 |
| 4 | TABLE ACCESS FULL | T2 | 3 | 9 | 2 (0)| 00:00:01 |
—————————————————————————–
Note
—–– dynamic sampling used for this statement (level=2)
由于笛卡尔链接会导致性能很差的SQL,因此一般也很少用到。
哈希链接( HASH JOIN )
当内存能够提供足够的空间时,哈希(HASH)链接是Oracle优化器通常的选择。哈希链接中,优化器根据统计信息,首先选择两个表中的小表,在内存中建立这张表的基于链接键的哈希表;优化器再扫描表链接中的大表,将大表中的数据与哈希表进行比较,如果有相关联的数据,则将数据添加到结果集中。
当表链接中的小表能够完全cache到可用内存的时候,哈希链接的效果最佳。哈希链接的成本只是两个表从硬盘读入到内存的成本。但是,如果哈希表过大而不能全部cache到可用内存时,优化器将会把哈希表分成多个分区,再将分区逐一cache到内存中。当表的分区超过了可用内存时,分区的部分数据就会临时地写到磁盘上的临时表空间上。因此,分区的数据写磁盘时,比较大的区间(EXTENT)会提高I/O性能。当哈希表构建完成后,进行下面的处理。
第二个大表进行扫描。
如果大表不能完全cache到可用内存的时候,大表同样会分成很多分区。
大表的第一个分区cache到内存。
对大表第一个分区的数据进行扫描,并与哈希表进行比较,如果有匹配的记录,添加到结果集里面。
与第一个分区一样,其他的分区也类似处理。
所有的分区处理完后,Oracle对产生的结果集进行归并,汇总,产生最终的结果。
当哈希表过大或可用内存有限,哈希表不能完全Cache到内存。随着满足链接条件的结果集的增加,可用内存会随之下降,这时已经Cache到内存的数据可能会重新写回到硬盘去。如果出现这种情况,系统的性能就会下降。当链接的两个表是用等值链接并且表的数据量比较大时,优化器才可能采用哈希链接。哈希链接是基于CBO的。只有在数据库初始化参数HASH_JOIN_ENABLED设为True,并且为参数PGA_AGGREGATE_TARGET设置了一个足够大的值的时候,Oracle才会使用哈希链接。HASH_AREA_SIZE是向下兼容的参数,但在Oracle 9i之前的版本中应当使用HASH_AREA_SIZE。当使用ORDERED提示时,FROM子句中的第一张表将用于建立哈希表。可以通过在SQL语句中添加HINTS /+ use_hash(a b)/ 强制Oracle优化器产生哈希链接的执行计划。
SQL> select /*+ use_hash(t1 t2)*/t1.col1,t1.col2,t2.col3 from t1,t2 where t1.col2=t2.col2;
Execution Plan
———————————————————-
Plan hash value: 1838229974
—————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————
| 0 | SELECT STATEMENT | | 3 | 60 | 6 (0)| 00:00:01 |
|* 1 | HASH JOIN | | 3 | 60 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| T1 | 3 | 45 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T2 | 3 | 15 | 3 (0)| 00:00:01 |
—————————————————————————
Predicate Information (identified by operation id):
—————————————————
1 – access("T1"."COL2"="T2"."COL2")
当缺少有用的索引时,哈希链接比嵌套循环链接更加有效。哈希链接也可能比嵌套循环链接更快,因为处理内存中的哈希表比检索B_树索引更加迅速。
反连接( Anti Join )
反连接是一种特殊的连接类型,当做子查询展开时,Oracle经常会把那些外部where条件为NOT EXISTS、NOT IN、<>ALL的子查询转换成对应的反连接。
反连接示例
分别执行以下三条SQL
select * from t1 where col2 not in (select col2 from t2);
select * from t1 where col2 <>all(select col2 from t2);
select * from t1 where not exists (select 1 from t2 where col2=t1.col2);
SQL> select * from t1 where col2 not in (select col2 from t2);
COL1 CO
———- —
3 C
Execution Plan
———————————————————-
Plan hash value: 1275484728
—————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————
| 0 | SELECT STATEMENT | | 3 | 51 | 6 (0)| 00:00:01 |
|* 1 | HASH JOIN ANTI NA | | 3 | 51 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| T1 | 3 | 45 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T2 | 3 | 6 | 3 (0)| 00:00:01 |
—————————————————————————
Predicate Information (identified by operation id):
—————————————————
1 – access("COL2"="COL2")
SQL> select * from t1 where col2 <>all(select col2 from t2);
COL1 CO
———- —
3 C
Execution Plan
———————————————————-
Plan hash value: 1275484728
—————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————
| 0 | SELECT STATEMENT | | 3 | 51 | 6 (0)| 00:00:01 |
|* 1 | HASH JOIN ANTI NA | | 3 | 51 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| T1 | 3 | 45 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| T2 | 3 | 6 | 3 (0)| 00:00:01 |
—————————————————————————
Predicate Information (identified by operation id):
—————————————————
1 – access("COL2"="COL2")
SQL> select * from t1 where not exists (select 1 from t2 where col2=t1.col2);
COL1 CO
———- —
3 C
Execution Plan
———————————————————-
Plan hash value: 1534930707
—————————————————————————–
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————–
| 0 | SELECT STATEMENT | | 3 | 51 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS ANTI | | 3 | 51 | 3 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| T1 | 3 | 45 | 3 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | IDX_T2 | 1 | 2 | 0 (0)| 00:00:01 |
—————————————————————————–
Predicate Information (identified by operation id):
—————————————————
3 – access("COL2"="T1"."COL2")
由于表t1 t2的各自连接列col2上均没有NULL值,在这种情况下,上面三个SQL其实是等价的。所有的执行计划里面都有ANTI,说明在执行上面的SQL时,的确是用的反连接。
当表的连接列中有了NULL值的时候,这三个SQL就不完全等价了,这种影响又细分为两种情况。
1.t1表的连接列上出现NULL值
SQL> insert into t1 values (4,null);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t1;
COL1 COL2
———- —–
1 A
2 B
3 C
4
–重新执行刚才的三个SQL
SQL> select * from t1 where col2 not in (select col2 from t2);
COL1 COL2
———- —–
3 C
SQL> select * from t1 where col2 <>all(select col2 from t2);
COL1 COL2
———- —–
3 C
SQL> select * from t1 where not exists (select 1 from t2 where col2=t1.col2);
COL1 COL2
———- —–
3 C
4
2.T2表的连接列出现NULL
SQL> delete from t1 where col1=4;
1 row deleted.
SQL> insert into t2 values (null,‘E2’);
1 row created.
SQL> commit;
Commit complete.
SQL> select * from t2;
COL2 COL3
—– —-
A A2
B B2
D D2
E2
–重新执行上面的三个SQL
SQL> select * from t1 where col2 not in (select col2 from t2);
no rows selected
SQL> select * from t1 where col2 <>all(select col2 from t2);
no rows selected
SQL> select * from t1 where not exists (select 1 from t2 where col2=t1.col2);
COL1 COL2
———- —–
3 C
结论:
(1) 当表的连接列出现了NULL值,上述范例中的SQL就不等价了。
(2) NOT IN 和 <>ALL 对NULL值敏感,这意味着NOT IN后面的子查询或常量集合一旦有NULL值出现,则整个SQL的执行结果就会为NULL,不会包含任何记录
(3) NOT EXISTS对NULL值不敏感,也就是说NULL值对NOT EXISTS的执行结果不会有什么影响。
为了解决NOT IN 和 <>ALL 对NULL值敏感,Oracle推出了改良的反连接,被称为Null-Aware Anti Join,执行计划中出现的HASH JOIN ANTI NA,这个关键字NA就是Null-Aware的缩写,这里oracle就是要告知所采用的不是普通的hash反连接,而是改良的反连接,是可以处理null值的。Oracle是否启用Null-Aware Anti Join受隐含参数_OPTIMIZER_NULL_AWARE_ANTIJOIN控制,默认是TRUE,表示启用Null-Aware Anti Join。
改良反连接示例
如果把该隐含参数改为FALSE,则Oracle不能再用改良反连接,而又因为NOT IN对NULL值敏感,所以Oracle此时也不能用普通的反连接。
SQL> alter session set "_OPTIMIZER_NULL_AWARE_ANTIJOIN" = false;
Session altered.
SQL> select * from t1 where col2 <>all(select col2 from t2);
COL1 CO
———- —
3 C
Execution Plan
———————————————————-
Plan hash value: 895956251
—————————————————————————
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————
| 0 | SELECT STATEMENT | | 1 | 15 | 5 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL| T1 | 3 | 45 | 3 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| T2 | 3 | 6 | 2 (0)| 00:00:01 |
—————————————————————————
Predicate Information (identified by operation id):
—————————————————
1 – filter( NOT EXISTS (SELECT 0 FROM "T2" "T2" WHERE
LNNVL("COL2"<>:B1)))
3 – filter(LNNVL("COL2"<>:B1))
可以看到这里的执行计划走了FILTER,而不再是HASH JOIN ANTI NA。
半连接( Semi Join )
半连接是一种特殊的连接类型,与反连接一样,Oracle数据库里面也没有相关的关键字可以在SQL文本中专门表示半连接。半连接和普通的内连接不同,半连接会去重。
半连接示例
分别执行以下三条SQL
select * from t1 where col2 in (select col2 from t2);
select * from t1 where col2=any (select col2 from t2);
select * from t1 where exists (select 1 from t2 where col2=t1.col2);
SQL> select * from t1 where col2 in (select col2 from t2);
COL1 CO
———- —
1 A
2 B
Execution Plan
———————————————————-
Plan hash value: 3783859632
—————————————————————————–
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————–
| 0 | SELECT STATEMENT | | 3 | 51 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS SEMI | | 3 | 51 | 3 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| T1 | 3 | 45 | 3 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | IDX_T2 | 3 | 6 | 0 (0)| 00:00:01 |
—————————————————————————–
SQL> select * from t1 where col2=any (select col2 from t2);
COL1 CO
———- —
1 A
2 B
Execution Plan
———————————————————-
Plan hash value: 3783859632
—————————————————————————–
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————–
| 0 | SELECT STATEMENT | | 3 | 51 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS SEMI | | 3 | 51 | 3 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| T1 | 3 | 45 | 3 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | IDX_T2 | 3 | 6 | 0 (0)| 00:00:01 |
—————————————————————————–
SQL> select * from t1 where exists (select 1 from t2 where col2=t1.col2);
COL1 CO
———- —
1 A
2 B
Execution Plan
———————————————————-
Plan hash value: 3783859632
—————————————————————————–
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
—————————————————————————–
| 0 | SELECT STATEMENT | | 3 | 51 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS SEMI | | 3 | 51 | 3 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL| T1 | 3 | 45 | 3 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | IDX_T2 | 3 | 6 | 0 (0)| 00:00:01 |
—————————————————————————–
上述三个SQL的执行结果是一样的,而且它们的执行计划的现实内容均有关键字SEMI,这个关键字就说明Oracle执行这三个SQL是在用半连接。
主要表连接方式比较
| 特性 | 嵌套循环连接 (NESTED LOOP) | 排序合并连接 (SORT MERGE) | 哈希连接 (HASH JOIN) |
|---|---|---|---|
| 优化器提示 | USE_NL |
USE_MERGE |
USE_HASH |
| 连接条件 | 任何连接条件 | 主要用于非等值连接(<,<=,>,>=) | 仅用于等值连接(=) |
| 资源消耗 | CPU、磁盘I/O | 内存、临时空间 | 内存、临时空间 |
| 最佳适用场景 | - 高选择性索引 - 限制性搜索 |
- 缺乏有效索引 - 大表连接 |
- 缺乏索引 - 数据仓库环境 |
| 首次返回速度 | (最快) | (较慢) | (较慢) |
| 整体吞吐量 | |||
| 内存需求 | |||
| 索引依赖 | 高度依赖 | 不依赖 | 不依赖 |
表的连接方式介绍(NESTED LOOP, SORT MERGE JOIN, HASH JOIN )的更多相关文章
- Oracle 表的连接方式(1)-----Nested loop join和 Sort merge join
关系数据库技术的精髓就是通过关系表进行规范化的数据存储,并通过各种表连接技术和各种类型的索引技术来进行信息的检索和处理. 表的三种关联方式: nested loop:从A表抽一条记录,遍历B表查找匹配 ...
- Nested Loop,Sort Merge Join,Hash Join
三种连接工作方式比较: Nested loops 工作方式是从一张表中读取数据,访问另一张表(通常是索引)来做匹配,nested loops适用的场合是当一个关联表比较小的时候,效率会更高. Merg ...
- 数据库多表连接方式介绍-HASH-JOIN
1.概述 hash join是一种数据库在进行多表连接时的处理算法,对于多表连接还有两种比较常用的方式:sort merge-join 和 nested loop. 为了比较清楚的介绍hash joi ...
- SQL Tuning 基础概述06 - 表的关联方式:Nested Loops Join,Merge Sort Join & Hash Join
nested loops join(嵌套循环) 驱动表返回几条结果集,被驱动表访问多少次,有驱动顺序,无须排序,无任何限制. 驱动表限制条件有索引,被驱动表连接条件有索引. hints:use_n ...
- [转]Apache HTTP Server 与 Tomcat 的三种连接方式介绍
首先我们先介绍一下为什么要让 Apache 与 Tomcat 之间进行连接.事实上 Tomcat 本身已经提供了 HTTP 服务,该服务默认的端口是 8080,装好 tomcat 后通过 8080 端 ...
- Oracle 表的连接方式(2)-----HASH JOIN的基本机制1
我们对hash join的常见误解,一般包括两个: 第一个误解:是我们经常以为hash join需要对两个做join的表都做全表扫描 第二个误解:是经常以为hash join会选择比较小的表做buil ...
- sort merge join,hash join,netsloop join
Join Operations ? SORT-MERGE JOIN – Sorts tables on the join key and then merges them together – Sor ...
- Oracle 表的连接方式
1. 连接说明 ① Oracle一次只能连接两个表.不管查询中有多少个表,Oracle 在连接中一次仅能操作两张表. ② 当执行多个表的连接时,优化器从一个表开始,将它与另一个表连接:然后将中间结果与 ...
- Oracle 表的连接方式(2)-----HASH JOIN的基本机制3
HASH JOIN的模式 hash join有三种工作模式,分别是optimal模式,onepass模式和multipass模式,分别在v$sysstat里面有对应的统计信息: SQL> sel ...
- Oracle 表的连接方式(2)-----HASH JOIN的基本机制2
Hash算法原理 对于什么是Hash算法原理?这个问题有点难度,不是很好说清楚,来做一个比喻吧:我们有很多的小猪,每个的体重都不一样,假设体重分布比较平均(我们考虑到公斤级别),我们按照体重来分,划分 ...
随机推荐
- JDK7-日历类--java进阶day07
1.Calendar类 用于获取或者修改时间,之前学的Date类,获取和修改时间的方法已经过时 2.Calendar对象的创建 Calendar类里面有很多抽象方法,如果创建对象就要全部重写,所以不能 ...
- 【JDBC第6章】数据库事务理论
第6章:数据库事务 6.1 数据库事务介绍 事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态. 事务处理(事务操作):保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方 ...
- sql server2005的死锁
select request_session_id spid, OBJECT_NAME(resource_associated_entity_id) tableName from sys.dm_tra ...
- Web前端入门第 27 问:你知道 CSS 被浏览器分为了几大类吗?
埋头苦写多年的 CSS,从没注意到 CSS 被浏览器分了类,直到偶然的一次翻阅开发者工具,才发现原来 CSS 属性也被浏览器归类收纳了. Chrome 下面是 Chrome 的开发者工具中 CSS 的 ...
- 使用Python解析求解扩散方程
引言 大家好!今天我们来探讨一个非常重要的物理问题-扩散方程,并用 Python 来求解它.扩散现象广泛存在于自然界中,从气体.液体中分子的扩散,到热量的传递,甚至污染物的扩散,都是扩散方程的应用场景 ...
- 使用Python建模量子隧穿
引言 量子隧穿是量子力学中的一个非常有趣且令人神往的现象.在经典物理学中,我们通常认为粒子必须克服一个势垒才能通过它.但是,在量子力学中,粒子有时可以"穿越"一个势垒,即使它的能量 ...
- Eclipse 安装---windows10环境下
Eclipse 安装---windows10环境下 一.下载 1.前往eclipse官网下载 https://www.eclipse.org/downloads/ 2.选择类型(压缩包) 3.选择版本 ...
- layui动态渲染select表单、初始化默认值、change事件监听等
layui动态渲染,初始化默认值 var html = ''; html += '<select name="" lay-search lay-verify="re ...
- 【完结】【一本通提高】KMP做题记录
题目编号 标题 估分 正确 提交 Y 2076 Problem A [一本通提高篇KMP]剪花布条 --- 156 293 Y 2077 Problem B [一本通提高篇KMP]Radio Tr ...
- 【ROS】4.1 Turtlebot3仿真Waffle循线跟踪
原视频 本节内容较多,请根据左侧目录针对性阅读. 一.准备工作 这一章我们先用gazebo仿真做,不使用真小车,使用的是Waffle模型. 需要下载的库gazebo-ros.turtlebot3_si ...