- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。
如果想找id为8的学生的信息,没有索引,此时的查找过程就相当于一个“顺序表查找”。
如果是针对顺序表查找,顺序表也是在内存当中,内存访问的速度快,并且数据也没那么多的时候,还可以勉强接受。
如果是针对数据库顺序查找,数据库的数据是在磁盘上,磁盘访问的速度更慢,并且数据量也可能非常多。这样速度就可能会变慢。
索引就是为了避免数据库进行顺序查找,提高查找效率。
索引可以考虑的数据结构有两种:1.哈希表 2.二叉搜索树 ,因为它们查找的速度都比较快。哈希表查找的时间复杂度O(1),二叉搜索树查找的时间复杂度O(logN)。
但是索引用这两种作为数据结构会有些缺点:
例如查找id<6并且>3的学生的信息。select * from student where id<6 and id>3;
哈希表用来作为索引数据结构的缺点:
我们都知道哈希表下的每个结点都是由链表连接起来的,哈希表的查找过程是把key代入哈希函数,计算得到下标,再根据下标取到对应的链表,再去遍历比较key是否相等。因此哈希表只能处理相等的情况,不能处理其它的逻辑(> >= < <= , between…and)等
二叉搜索树用来作为索引数据结构的缺点:
相比于哈希表,二叉搜索树虽然能处理范围查找,但是处理效率不高。
1.二叉搜索数每个结点最多两个叉,当数据量比较大的时候,树的高度就会较高,最终的操作效率也就会越低。
2.二叉搜索树直接获取到中序遍历也不是很高效O(N)
二叉搜索树的其它缺点:
因此:索引的数据结构是B+树,但要了解B+树之前要先了解B树。
B树也称为B-树(不是B减数),它是基于二叉搜索树来进行优化的。
叶子和非叶子都是由存储数据的,,都要放到磁盘上。
它是一棵N叉树,因此它的高度肯定会比二叉树的高度低,因此查找的效率更快。
它跟二叉树相比最大的差异:
1.每个结点不是2叉,而是n叉。
2.每个结点不是存一个数据了,而是可能存多个。
仔细观察能够发现,每个结点的存的数据的个数和该结点的度是相关的。
度=存的个数+1.
将B树中的一小部分截取下来:
B+树的存储结构:
非叶子结点上的数据相当于id,它能够快速找到叶子结点中对应的id,并获取id对应的数据。
和B树相比,主要是两个地方发生了变化:
1.每一层的元素之间都链接到了一起。
2.数据只在叶子结点上保存,非叶子结点上只保存一些辅助查找的边界信息。
B+树更多的优点:
索引起到的作用:加快查找效率,减慢插入和删除,修改效率(需要同步调整索引结果)
索引也会占到额外的内存空间(本质上用时间换取空间)
给具体的表中某列加索引的时候,加在主键上的索引(主键索引)和加在其它列上的索引是截然不同的。
主键索引的叶子结点存的是数据的完整记录,其它索引的叶子结点存的是主键的id。
例如:我们在创建表的时候给id加上主键,那主键索引就为id。此时要查找名字为李四的id,因为其它索引是存的id值。因此会先找到李四对应的主键id值,**再根据主键id去主键索引中查找id为1的全部数据,根据主键id在表中查找主键索引id的操作称为回表。**每条数据可能是一条长记录。
索引的应用场景主要是应用在查找很频繁,但是插入,删除,修改都不频繁的场景,这种场景非常常见。
需要考虑以下几点:
满足以上条件时,考虑对表中的这些字段创建索引,以提高查询效率。
反之,如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。
创建主键约束(primary key)、唯一约束(unique)、外键约束时(foreign key),会自动创建对应的列的索引。
如:当我们的一个student表的id要关联于class表中的学生的id,创建的主键id是在class表当中的。因此这样才能确定该班中的学生有谁。
show index from 表名;
案例:查看学生表已有的索引
show index from student;
对于非主键、非唯一约束、非外键的字段,可以创建普通索引。
create index 索引名 on 表名(字段名);
案例:创建学生中name字段的索引
create index index_name_student on student(name);
drop index 索引名 on 表名;
案例:删除班级表中name字段的索引
drop index index_name_student on student;
索引的创建和删除都是耗时操作,因此不必要的时候已经创建好索引的情况下尽量少去自己创建索引,并且不要在生产环境中创建索引。
面试问题总结:
1.索引是啥?
2.索引要解决的问题
3.索引的应用场景
4.索引的数据结构
a) 为什么不用哈希表
b) 为什么不用二叉搜索树
c) 啥是B树,相较上面两个有什么优势
d) 啥是B+树,为什么用它来作索引的数据结构
5.更详细的说下索引的细节方面
事务解决的问题:
例如有个数据表,保存了一些人的银行账户余额,接下来需要进行A->B转账3000块钱。
可以分为两个步骤:
1.A的账户余额减3000
2.B的账户余额加3000
但是,如果1执行成功了,执行2的时候出了问题,此时A 的钱减少了而B的没有增加,3000块钱是不是就凭空消失了呢?
因此事务的概念:
把一组操作封装到一起,称为一个共同的执行单元,此时执行整个事务就能避免上面的问题。
事务的特性总称为ACID。
a) 原子性:事务中的若干个操作,要么全部执行成功,要么全部都不执行。但此处的不执行并不是真正的不执行,而是一旦中间某个步骤执行出错,就把前面已经执行完毕的步骤回滚(rollback)回去。步骤回滚要借助逆向操作,目的是把原来操作造成的影响进行还原。例如:减3000的逆操作就是加3000.
b) 一致性:执行事务的前后,数据始终处于一种合法的状态,例如转账操作,减账户余额的时候,不能账户余额减成负数。
c) 持久性:事务一旦执行完毕,此时对于数据的修改就是持久生效的(写入磁盘了)。注:数据存到磁盘中就是持久的,数据存到内存中就是不持久的(重启就没了)
d) 隔离性:比较复杂,设计到“并发执行事务”,它能够引发一系列的问题:脏读、不可重复读、幻读 => 解决方案 => 数据库隔离级别 。
(1)开启事务:start transaction;
(2)执行多条SQL语句
(3)回滚或提交:rollback/commit;
说明:rollback即是全部失败,commit即是全部成功。
start transaction;
-- 阿里巴巴账户减少2000
update accout set money=money-2000 where name = '阿里巴巴';
-- 四十大盗账户增加2000
update accout set money=money+2000 where name = '四十大盗';
commit;
我正在使用 PostgREST 将数据库实体暴露给使用这些实体的 Springboot 应用。 我的数据库中有两个实体,分别是 Person 和 City。 我想同时保存 Person 实体和 Cit
1、事务的定义 Redis的事务提供了一种“将多个命令打包, 然后一次性、按顺序地执行”的机制。 redis事务的主要作用就是串联多个命令防止别的命令插队。 但是,事务并不具有传统
SQLite 事务(Transaction) 事务(Transaction)是一个对数据库执行工作单元。事务(Transaction)是以逻辑顺序完成的工作单位或序列,可以是由用户手动操作完成,也可
事务是顺序组操作。 它们作为单个单元运行,并且直到组中的所有操作都成功执行时才终止。 组中的单个故障会导致整个事务失败,并导致对数据库没有影响。 事务符合ACID(原子性,一致性,隔离和耐久性)
我希望将 SqlKata 用于一个项目。但是,项目标准的一部分是查询应该能够作为事务执行。有没有一种方法可以使用 MSSQL 事务执行一个查询或多个查询? 非常感谢。 最佳答案 SQLKata 使用
我只是以多线程方式测试 PetaPoco 事务... 我有一个简单的测试用例: -- 简单的值对象称之为 MediaDevice -- 插入一条记录,更新1000次 void TransactionT
我正在尝试从 Excel VBA 向 SQL 中插入一些数据。 SQL 命令是在 VBA 脚本的过程中构建的,包括使用一些 SQL 变量。 我试图了解事务在 VBA 中是如何工作的,以及它们是否可以处
情况如下: 一个大型生产客户端/服务器系统,其中一个中央数据库表具有某个列,该列的默认值是 NULL,但现在默认值是 0。但是在该更改之前创建的所有行当然仍然具有 null 值,这会在该系统中生成许多
数据库事务是一个熟悉的概念。 try { ... .. updateDB() .. ... commit(); } catch error { rollback(); }
我想了解使用传播支持进行 Spring 交易的用途。 java 文档提到如果具有 @Transactional(propagation = Propagation.SUPPORTS) 的方法从支持该事
我需要获取 hibernate 的事务 ID。对于每笔交易,此 ID 必须是唯一的。我尝试使用 session.getTransaction().hashCode(),但我相信这个值不是唯一的。 最佳
我从 firebase 收到以下消息:runTransactionBlock:启用持久性时检测到的使用情况。请注意,事务不会在应用重新启动后保留。 那么应用程序重新启动后到底会发生什么?由于主数据库的
我需要在 jdbc 中执行选择、更新、插入查询的序列。 这是我的代码: public String editRequest(){ connection = DatabaseUtil.getServi
Java 是否提供了一种智能“聚合”事务的方法?如果我有多个异构数据存储库,我想保持同步(即用于数据的 Postgres、用于图表的 Neo4j 以及用于索引的 Lucene),是否有一个范例仅允许
我对标题中的主题有几个问题。首先,假设我们使用 JDBC,并且有 2 个事务 T1 和 T2。在 T1 中,我们在一个特定的行上执行 select 语句。然后我们对该行执行更新。在事务 T2 中,我们
我有一个 Python CGI 处理支付交易。当用户提交表单时,CGI 被调用。提交后,CGI 需要一段时间才能执行信用卡交易。在此期间,用户可能会按下 ESC 或刷新按钮。这样做不会“杀死”CGI,
我有一个代码,类似这样 def many_objects_saving(list_of_objects): for some_object in list_of_objects:
我有一个包含 100,000 条记录的表。我正在考虑使用事务来更新数据。将有一个查询将一列更新为零,并且大约有 5000 个更新,每个更新将更新一条记录。 这些大型事务对内存有何影响?事务运行时选择数
有没有办法在一个命令中执行 SQL 事务?例如 mysql_query(" START TRANSACTION; INSERT INTO table1 ....etc; INSERT INTO tab
真心希望能帮到你! 我使用以下函数在 PHP/MySql 应用程序中发送消息: public function sendMail($sender_id, $recipient_id, $subject
我是一名优秀的程序员,十分优秀!