响应式网站是做列表/网络营销教学大纲
1.1 创建普通B-tree索引的整体流程
如下是梳理的创建普通B-tree索引的大概流程,可供参考。
1.校验新索引的Catalog元数据|语法解析 ---将创建索引的sql解析成IndexStmt结构|校验B-Tree的handler -----校验内核是否支持该类型的索引,在pg_am中查找"btree"对应的handler|校验索引列及比较函数 ----查找pg_attribute,校验create index中指定的索引列是否存在,如果存在记录attno,并且根据atttypid(表示表中列的字段类型)在pg_opclass里查找对应的比较函数2.在文件系统中创建索引文件|生成oid ---为新的索引文件生成唯一oid,过程是:生成一个新的oid,然后查找pg_class的索引,如果不存在就返回这个oid|更新本地的relcache ---正在创建的relation添加到relcache|创建索引文件以及写xlog ----文件系统中生成新的文件 base/xxx/xxx。xlog记录类型为XLogInsert(RM_SMGR_ID, XLOG_SMGR_CREATE | XLR_SPECIAL_REL_UPDATE)3.创建新索引的元数据|索引作为对象的元数据写入到pg_class |索引文件引用的列插入pg_attribute|索引本身相关信息插入pg_index|relcache失效,invalid所有heap相关的元数据 ---为了使catalog元数据的变更对所有进程生效|记录该索引对heap的依赖,对opclass的依赖等等插入pg_depend|使得新索引文件相关的relcache生效4.用函数btbuild构建B-tree索引|通过index的索引列构建排序时需要用到的sortkey,扫描tuple生成索引元组数组| 构建B+树叶节点|对索引元组执行排序|将排序成功的结点依次插入到B-Tree中,自下向上构建B-Tree索引page --依次读取排好序的tuple,填充到B-Tree的叶子节点上,自下向上插入B-Tree
1.2 锁相关介绍
PostgreSQL里有很多可以加锁的对象:表、单个页、单个元组、事务ID(包括虚拟和永久ID)和普通数据库对象等等,常规锁的locktype主要有以下几种。有时候通过pg_locks查询的时候,根据pid会查到许多的锁,但是这些锁并不一定都是加在表上的,根据locktype以及relation过滤出不同对象上的锁。
/** LOCKTAG is the key information needed to look up a LOCK item in the* lock hashtable. A LOCKTAG value uniquely identifies a lockable object.** The LockTagType enum defines the different kinds of objects we can lock.* We can handle up to 256 different LockTagTypes.*/
typedef enum LockTagType
{LOCKTAG_RELATION, /* whole relation */LOCKTAG_RELATION_EXTEND, /* the right to extend a relation */LOCKTAG_DATABASE_FROZEN_IDS, /* pg_database.datfrozenxid */LOCKTAG_PAGE, /* one page of a relation */LOCKTAG_TUPLE, /* one physical tuple */LOCKTAG_TRANSACTION, /* transaction (for waiting for xact done) */LOCKTAG_VIRTUALTRANSACTION, /* virtual transaction (ditto) */LOCKTAG_SPECULATIVE_TOKEN, /* speculative insertion Xid and token */LOCKTAG_OBJECT, /* non-relation database object */LOCKTAG_USERLOCK, /* reserved for old contrib/userlock code */LOCKTAG_ADVISORY /* advisory user locks */
} LockTagType;
如下是PostgreSQL里的常规锁,其中AccessShareLock、RowShareLock、RowExclusiveLock属于弱锁,ShareLock、ShareRowExclusiveLock、ExclusiveLock 、AccessExclusiveLock属于强锁。
/* NoLock is not a lock mode, but a flag value meaning "don't get a lock" */
#define NoLock 0
#define AccessShareLock 1 /* SELECT */
#define RowShareLock 2 /* SELECT FOR UPDATE/FOR SHARE */
#define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */
#define ShareUpdateExclusiveLock 4 /* VACUUM (non-FULL),ANALYZE, CREATE * INDEX CONCURRENTLY */
#define ShareLock 5 /* CREATE INDEX (WITHOUT CONCURRENTLY) */
#define ShareRowExclusiveLock 6 /* like EXCLUSIVE MODE, but allows ROW * SHARE */
#define ExclusiveLock 7 /* blocks ROW SHARE/SELECT...FOR * UPDATE */
#define AccessExclusiveLock 8 /* ALTER TABLE, DROP TABLE, VACUUM * FULL, and unqualified LOCK TABLE */
1.3 创建普通索引表上需要获取的锁(ShareLock)
使用如下的语句进行测试
postgres=# create table tab_test_1(id int);
CREATE TABLE
postgres=# insert into tab_test_1 values(1);
INSERT 0 1
postgres=# insert into tab_test_1 values(2);
INSERT 0 1
postgres=# insert into tab_test_1 values(3);
INSERT 0 1
postgres=# begin;
BEGIN
postgres=*# create index idx_1 on tab_test_1(id);
CREATE INDEX
postgres=*#
普通创建索引获取ShareLock,是5级锁,这里通过SQL可以查询到,其实在创建索引的过程中,不仅原始的表上会申请锁。对应的几张系统表和系统表索引上也会申请锁,因为创建索引也涉及到系统表元数据的校验和更改,这里访问pg_namespace的意义在于:索引将与其父表位于同一命名空间中。
当有多个事务同时对表进行读操作时,如果不做任何锁定,会导致数据不一致。例如,一个事务在读取数据时,另一个事务做了修改,然后第一个事务读到的数据已经不是最新的。这时候就需要使用AccessShareLock来控制并发的读取操作,保持数据的一致性。
postgres=# select l.locktype,ns.nspname,a.relname,a.relkind,l.pid,l.mode,l.granted,p.query_start,p.query,p.state from pg_locks l,pg_stat_activity p,pg_class a,pg_namespace ns where l.locktype='relation' and l.pid=p.pid and query not like '%pg_stat_activity%' and l.relation=a.oid and a.relnamespace=ns.oid;locktype | nspname | relname | relkind | pid | mode | granted | query_start |query | state
----------+------------+-----------------------------------+---------+--------+-----------------+---------+-------------------------------+-----------
----------------------------+---------------------relation | public | tab_test_1 | r | 409706 | ShareLock | t | 2024-01-04 11:48:11.807816+08 | create index idx_1 on tab_test_1(id); | idle in transactionrelation | pg_catalog | pg_class | r | 409706 | AccessShareLock | t | 2024-01-04 11:48:11.807816+08 | create index idx_1 on tab_test_1(id); | idle in transactionrelation | pg_catalog | pg_namespace | r | 409706 | AccessShareLock | t | 2024-01-04 11:48:11.807816+08 | create index idx_1 on tab_test_1(id); | idle in transactionrelation | pg_catalog | pg_namespace_nspname_index | i | 409706 | AccessShareLock | t | 2024-01-04 11:48:11.807816+08 | create index idx_1 on tab_test_1(id); | idle in transactionrelation | pg_catalog | pg_namespace_oid_index | i | 409706 | AccessShareLock | t | 2024-01-04 11:48:11.807816+08 | create index idx_1 on tab_test_1(id); | idle in transactionrelation | pg_catalog | pg_class_oid_index | i | 409706 | AccessShareLock | t | 2024-01-04 11:48:11.807816+08 | create index idx_1 on tab_test_1(id); | idle in transactionrelation | pg_catalog | pg_class_relname_nsp_index | i | 409706 | AccessShareLock | t | 2024-01-04 11:48:11.807816+08 | create index idx_1 on tab_test_1(id); | idle in transactionrelation | pg_catalog | pg_class_tblspc_relfilenode_index | i | 409706 | AccessShareLock | t | 2024-01-04 11:48:11.807816+08 | create index idx_1 on tab_test_1(id); | idle in transaction
(8 rows)
1.4 关于ShareLock的其他场景
在源码的注释部分,可以看到CREATE INDEX (WITHOUT CONCURRENTLY) 的时候会在表上申请ShareLock,这和我们的测试结果相符合,但是ShareLock不仅仅创建索引的时候会获取,当多个事务更新同一行的时候,也会申请ShareLock,不过这个ShareLock不是在表级别申请的,而是在分配事务ID时对这个事务ID进行加锁, 用于元组并发更新时做事务等待。
分别用两个session做如下操作:
//session 1,pid:434865postgres=# begin;
BEGIN
postgres=*# update tab_test_1 set id=7 where id=1;
UPDATE 1
postgres=*#//session 2,pid:433290postgres=# begin;
BEGIN
postgres=*# update tab_test_1 set id=7 where id=1;
然后用另一个session查询锁的状态
postgres=# select * from pg_locks where pid='434865';locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | pid | mode| granted | fastpath | waitstart
---------------+----------+----------+------+-------+------------+---------------+---------+-------+----------+--------------------+--------+--------------
----+---------+----------+-----------relation | 13008 | 16725 | | | | | | | | 3/16 | 434865 | RowExclusiveL
ock | t | t |virtualxid | | | | | 3/16 | | | | | 3/16 | 434865 | ExclusiveLock| t | t |transactionid | | | | | | 1699 | | | | 3/16 | 434865 | ExclusiveLock| t | f |
(3 rows)postgres=# select * from pg_locks where pid='433290';locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | pid | mode| granted | fastpath | waitstart
---------------+----------+----------+------+-------+------------+---------------+---------+-------+----------+--------------------+--------+--------------
----+---------+----------+-------------------------------relation | 13008 | 16725 | | | | | | | | 4/3 | 433290 | RowExclusiveLock | t | t |virtualxid | | | | | 4/3 | | | | | 4/3 | 433290 | ExclusiveLock| t | t |transactionid | | | | | | 1700 | | | | 4/3 | 433290 | ExclusiveLock| t | f |tuple | 13008 | 16725 | 0 | 1 | | | | | | 4/3 | 433290 | ExclusiveLock| t | f |transactionid | | | | | | 1699 | | | | 4/3 | 433290 | ShareLock| f | f | 2024-01-04 13:33:16.667889+08
(5 rows)
可以通过上述测试看到,pid为433290的这个session,它的pg_locks的最后一行 的granted为’f’,说明该进程被阻塞,并且是在申请类型为tansactionid的锁时被阻塞了,对应tansactionid=1699的事务。从表上可以看出这个tansactionid已经被进程pid为434865的session1会话持有了。
行锁的阻塞信息是通过tansactionid类型的锁体现的,行锁是会在数据行上加自己的tansactionid的,另一个进程读到这一行时,如果发现上一个操作该行的事务未结束,会把上一个事务的tansactionid读出来,然后申请在这个tansactionid上加上ShareLock,等待上一个事务结束,再获得ExclusiveLock。而持有行锁的进程已经在此tansactionid上加了ExclusiveLock,所以后面要更新这行的进程会被阻塞。
ShareLock即读锁,ExclusiveLock即写锁。对事务ID加ShareLock是为了事务不提交,其他人看不到修改后的行,而ExclusiveLock是防止并发操作的。
1.5 创建普通索引时阻塞的一些操作
如下是对创建普通索引申请的ShareLock后的一些阻塞情况
1.5.1 建普通索引阻塞DML操作
//开一个session,开启事务创建索引,然后不提交postgres=# begin;
BEGIN
postgres=*# create index idx_1 on tab_test_1(id);
CREATE INDEX
postgres=*#//新开一个session,查询这张表,可以正常访问,不阻塞读
postgres=# select * from tab_test_1 ;id
----123
(3 rows)//新开多个session,分别做dml操作
//session A:
postgres=# insert into tab_test_1 values(6);
//session B:
postgres=# update tab_test_1 set id=7 where id=1;
//session C:
postgres=# delete from tab_test_1 where id=1;//另开一个session,查看获取的锁postgres=# select l.locktype,ns.nspname,a.relname,a.relkind,l.pid,l.mode,l.granted,p.query_start,p.query,p.state from pg_locks l,pg_stat_activity p,pg_class a,pg_namespace ns where l.locktype='relation' and l.pid=p.pid and query not like '%pg_stat_activity%' and l.relation=a.oid and a.relnamespace=ns.oid and a.relname='tab_test_1';locktype | nspname | relname | relkind | pid | mode | granted | query_start | query |state
----------+---------+------------+---------+--------+------------------+---------+-------------------------------+----------------------------------------+
---------------------relation | public | tab_test_1 | r | 409706 | ShareLock | t | 2024-01-04 11:48:11.807816+08 | create index idx_1 on tab_test_1(id); |idle in transactionrelation | public | tab_test_1 | r | 410009 | RowExclusiveLock | f | 2024-01-04 12:48:34.640655+08 | insert into tab_test_1 values(6); |activerelation | public | tab_test_1 | r | 420570 | RowExclusiveLock | f | 2024-01-04 12:48:37.450632+08 | update tab_test_1 set id=7 where id=1; |activerelation | public | tab_test_1 | r | 420581 | RowExclusiveLock | f | 2024-01-04 12:48:39.828598+08 | delete from tab_test_1 where id=1; |active
(4 rows)//以及查看阻塞源,可以看到表上的dml操作都是被create index 给阻塞了。pid | blocked_by | state | wait | wait_age | tx_age | xid_age | xmin_ttf | datname | usename | blkd | que
ry
--------+------------+---------+-------------------+----------+----------+---------+---------------+----------+----------+------+--------------------------
--------------------------409706 | {} | idletx | Client:ClientRead | | 01:02:44 | 5 | | postgres | postgres | 3 | [409706] create index idx_1 on tab_test_1(id);410009 | {409706} | waiting | Lock:relation | 00:01:57 | 00:01:57 | | 2,147,483,642 | postgres | postgres | 0 | [410009] . insert into tab_test_1 values(6);420570 | {409706} | waiting | Lock:relation | 00:01:54 | 00:01:54 | | 2,147,483,642 | postgres | postgres | 0 | [420570] . update tab_test_1 set id=7 where id=1;420581 | {409706} | waiting | Lock:relation | 00:01:51 | 00:01:51 | | 2,147,483,642 | postgres | postgres | 0 | [420581] . delete from tab_test_1 where id=1;
(4 rows)
1.5.2 建普通索引阻塞DDL操作
//开一个session,开启事务创建索引,然后不提交postgres=# begin;
BEGIN
postgres=*# create index idx_1 on tab_test_1(id);
CREATE INDEX
postgres=*#//新开一个session,执行DDL操作,alter table加列postgres=# alter table tab_test_1 add column name varchar(20);//另开一个session,查看获取的锁
postgres=# select l.locktype,ns.nspname,a.relname,a.relkind,l.pid,l.mode,l.granted,p.query_start,p.query,p.state from pg_locks l,pg_stat_activity p,pg_class a,pg_namespace ns where l.locktype='relation' and l.pid=p.pid and query not like '%pg_stat_activity%' and l.relation=a.oid and a.relnamespace=ns.oid and a.relname='tab_test_1';locktype | nspname | relname | relkind | pid | mode | granted | query_start | query| state
----------+---------+------------+---------+--------+---------------------+---------+-------------------------------+--------------------------------------
---------------+---------------------relation | public | tab_test_1 | r | 409706 | ShareLock | t | 2024-01-04 11:48:11.807816+08 | create index idx_1 on tab_test_1(id);| idle in transactionrelation | public | tab_test_1 | r | 422658 | AccessExclusiveLock | f | 2024-01-04 12:51:52.948432+08 | alter table tab_test_1 add column nam
e varchar(20); | active
(2 rows)//查看阻塞源,可以看到表上alter table加列的DDL操作被create index给阻塞了。pid | blocked_by | state | wait | wait_age | tx_age | xid_age | xmin_ttf | datname | usename | blkd |query
--------+------------+---------+-------------------+----------+----------+---------+---------------+----------+----------+------+--------------------------
---------------------------------------409706 | {} | idletx | Client:ClientRead | | 01:04:09 | 6 | | postgres | postgres | 1 | [409706] create index idx_1 on tab_test_1(id);422658 | {409706} | waiting | Lock:relation | 00:00:03 | 00:00:03 | 1 | 2,147,483,641 | postgres | postgres | 0 | [422658] . alter table tab_test_1 add column name varchar(20);
(2 rows)//新开一个session,执行DDL操作,drop table删除表
postgres=# drop table tab_test_1;//另开一个session,查看获取的锁postgres=# select l.locktype,ns.nspname,a.relname,a.relkind,l.pid,l.mode,l.granted,p.query_start,p.query,p.state from pg_locks l,pg_stat_activity p,pg_class a,pg_namespace ns where l.locktype='relation' and l.pid=p.pid and query not like '%pg_stat_activity%' and l.relation=a.oid and a.relnamespace=ns.oid and a.relname='tab_test_1';locktype | nspname | relname | relkind | pid | mode | granted | query_start | query| state
----------+---------+------------+---------+--------+---------------------+---------+-------------------------------+--------------------------------------
-+---------------------relation | public | tab_test_1 | r | 409706 | ShareLock | t | 2024-01-04 11:48:11.807816+08 | create index idx_1 on tab_test_1(id);| idle in transactionrelation | public | tab_test_1 | r | 422669 | AccessExclusiveLock | f | 2024-01-04 12:53:17.664053+08 | drop table tab_test_1;| active
(2 rows)//查看阻塞源,可以看到表上drop table删除表的DDL操作被create index给阻塞了。pid | blocked_by | state | wait | wait_age | tx_age | xid_age | xmin_ttf | datname | usename | blkd | quer
y
--------+------------+---------+-------------------+----------+----------+---------+---------------+----------+----------+------+--------------------------
-----------------------409706 | {} | idletx | Client:ClientRead | | 01:05:43 | 7 | | postgres | postgres | 1 | [409706] create index idx_1 on tab_test_1(id);422669 | {409706} | waiting | Lock:relation | 00:00:12 | 00:00:12 | 1 | 2,147,483,640 | postgres | postgres | 0 | [422669] . drop table tab_test_1;
(2 rows)
1.5.3 阻塞vacuum,vacuum full,analyze
//开一个session,开启事务创建索引,然后不提交postgres=# begin;
BEGIN
postgres=*# create index idx_1 on tab_test_1(id);
CREATE INDEX
postgres=*#//新开一个session,vacuum该表postgres=# vacuum tab_test_1;//另开一个session,查看获取的锁postgres=# select l.locktype,ns.nspname,a.relname,a.relkind,l.pid,l.mode,l.granted,p.query_start,p.query,p.state from pg_locks l,pg_stat_activity p,pg_class a,pg_namespace ns where l.locktype='relation' and l.pid=p.pid and query not like '%pg_stat_activity%' and l.relation=a.oid and a.relnamespace=ns.oid;locktype | nspname | relname | relkind | pid | mode | granted | query_start | query| state
----------+---------+------------+---------+--------+--------------------------+---------+-------------------------------+---------------------------------
------+---------------------relation | public | tab_test_1 | r | 452619 | ShareLock | t | 2024-01-04 14:50:00.524497+08 | create index idx_1 on tab_test_1
(id); | idle in transactionrelation | public | tab_test_1 | r | 452585 | ShareUpdateExclusiveLock | f | 2024-01-04 14:50:35.244644+08 | vacuum tab_test_1 ;| active
(2 rows)//查看阻塞源,可以看到表vacuum操作被create index给阻塞了。pid | blocked_by | state | wait | wait_age | tx_age | xid_age | xmin_ttf | datname | usename | blkd | quer
y
--------+------------+---------+-------------------+----------+----------+---------+---------------+----------+----------+------+--------------------------
-----------------------452619 | {} | idletx | Client:ClientRead | | 00:00:40 | 1 | | postgres | postgres | 1 | [452619] create index id
x_1 on tab_test_1(id);452585 | {452619} | waiting | Lock:relation | 00:00:02 | 00:00:02 | | 2,147,483,646 | postgres | postgres | 0 | [452585] . vacuum tab_te
st_1 ;
(2 rows)
可以看到vacuum改表被create index阻塞了,vacuum full,analyze测试方法类似,也是一样被阻塞了。
//阻塞vacuum fullpid | blocked_by | state | wait | wait_age | tx_age | xid_age | xmin_ttf | datname | usename | blkd | quer
y
--------+------------+---------+-------------------+----------+----------+---------+---------------+----------+----------+------+--------------------------
-----------------------452619 | {} | idletx | Client:ClientRead | | 00:12:38 | 2 | | postgres | postgres | 1 | [452619] create index id
x_1 on tab_test_1(id);452585 | {452619} | waiting | Lock:relation | 00:00:07 | 00:00:07 | 1 | 2,147,483,645 | postgres | postgres | 0 | [452585] . vacuum full t
ab_test_1 ;
(2 rows)//阻塞analyzepid | blocked_by | state | wait | wait_age | tx_age | xid_age | xmin_ttf | datname | usename | blkd | quer
y
--------+------------+---------+-------------------+----------+----------+---------+---------------+----------+----------+------+--------------------------
-----------------------452619 | {} | idletx | Client:ClientRead | | 00:14:04 | 2 | | postgres | postgres | 1 | [452619] create index id
x_1 on tab_test_1(id);452585 | {452619} | waiting | Lock:relation | 00:00:07 | 00:00:07 | | 2,147,483,645 | postgres | postgres | 0 | [452585] . analyze tab_t
est_1;
(2 rows)
1.6 创建普通B-tree索引的可能遇到的问题
问题:
创建普通B-tree索引在表上申请的是ShareLock,ShareLock和RowExclusiveLock是冲突的,所以create index会等待表上所有的DML(增删改)结束。但是实际在生产环境下,如果业务不停运行,涉及到要加索引的表不停的有DML操作,那么,执行了create index操作后,可能会发现长时间都没有反应,因为create index操作可能长时间获取不到锁,然后一直处于锁的等待队列里。
就算能获取到了锁,可以创建索引了,但是在创建索引期间,也会阻塞所有的DML(增删改),如果需要加索引的表是一个大表,并且需要加索引的这列数据也比较复杂,那么可能执行时间比较长,那么对DML的阻塞时间也会比较长,这对于某些业务场景可能是不能接受的。除了阻塞时间长一个问题外,如果建索引期间,业务较多,被阻塞的DML大量累积,有可能导致pg_locks里累积的越来越多,最后导致OOM。
解决方法:
(1)对于建索引的操作尽量选择业务量较少的时候执行,或者有条件在停业务的窗口内完成。
(2)设置lock_timeout,不让其长时间的获取锁,阻塞业务。
(3)可以使用create index concurrently 在线创建索引(CIC),降低了创建索引在表上申请的锁的级别,ShareUpdateExclusiveLock级别的锁和RowExclusiveLock不冲突,不会阻塞DML操作。
创建索引慢:
至于常见的创建索引慢的原因也可以参考我的这篇文章常见的创建索引慢的原因
相关文章:

【PostgreSQL创建索引的锁分析和使用注意】
1.1 创建普通B-tree索引的整体流程 如下是梳理的创建普通B-tree索引的大概流程,可供参考。 1.校验新索引的Catalog元数据|语法解析 ---将创建索引的sql解析成IndexStmt结构|校验B-Tree的handler -----校验内核是否支持该类型的索引,在pg_am中查找&q…...

什么是云安全?如何保护云资源
云计算允许组织通过互联网按需向其客户、合作伙伴或员工提供关键业务应用程序、服务和资源。换句话说,不再需要物理维护资源。每当您通过 Internet 从计算机访问文件或服务时,您都是在访问云。 迁移到云可以帮助企业增强安全性、简化运营并降低成本。企…...

Android可换行的RadioGroup
Android可换行的RadioGroup,有时候需要换行显示的单选列表,当然可以有多种实现方式,比如recycleview或者listview实现,本文采用的是RadioGrouprediobutton方式实现。 一、首先自定义view public class WrapRadioGroup extends RadioGroup {pr…...

【ASP.NET Core 基础知识】--环境设置
一、简介 1.1 .NET Core SDK 概述 .NET Core SDK(Software Development Kit)是Microsoft推出的一个开源跨平台框架,用于开发和部署.NET应用程序。它是.NET Core平台的核心组件之一,为开发者提供了在多个操作系统上构建高性能、可…...

docker/华为云cce 部署nacos 2.3.0 集群模式
镜像地址 https://hub.docker.com/r/nacos/nacos-server 版本 nacos/nacos-server:v2.3.0-slim 关键环境变量 使用mysql数据源 变量值备注MODEcluster启用集群模式MYSQL_SERVICE_DB_NAME数据库名MYSQL_SERVICE_USER数据库用户名MYSQL_SERVICE_PASSWORD数据库密码SPRING_D…...

Doris 数据模型—Aggregate 模型
Doris 数据模型—Aggregate 模型 文章目录 Doris 数据模型—Aggregate 模型基本概念Aggregate 模型示例1:导入数据聚合示例2:保留明细数据示例3:导入数据与已有数据聚合Aggregate 模型限制Aggregate 模型使用场景本文主要从逻辑层面,描述 Doris 的数据模型,以帮助用户更好…...

数据库管理-第130期 JSON二元性(20240109)
数据库管理130期 2024-01-09 第130期 JSON二元性(20240109)1 简介2 关系型表和JSON存储的优劣3 Oracle JSON关系型二元性视图总结 第130期 JSON二元性(20240109) 上周,又双叒飞了一趟上海,也是2024年第一飞…...

k8s--动态pvc和pv
前情回顾 存储卷: emptyDir 容器内部,随着pod销毁,emptyDir也会消失 不能做数据持久化 hostPath:持久化存储数据 可以和节点上目录做挂载。pod被销毁了数据还在 NFS:一台机器,提供pod内容器所有的挂载点…...

C++:常量
const的最初动机 const的使用方法 使用const的好处是允许指定一种语义上的约束,即某种对象不能被修改,且由编译器具体实施这种约束。 const声明格式:const 类型名 对象名;修饰普通变量,时期不能被随意修改 【注意】1.C中的const…...

java JDBC 连接数据库
必须先插入工具包 DataSource ds JdbcHelper.getDs();System.out.println(ds);JdbcTemplate jdbcTemplatenew JdbcTemplate(ds);System.out.println(jdbcTemplate);//新增String sql1"insert into biao values(null,?,?,?)";int ijdbcTemplate.update(sql1,"…...

图神经网络|5.消息传递的计算方法 6.多层GNN的作用
5.消息传递的计算方法 边的存放方式 注意,在实际的边的实现方式中,并不是以邻接矩阵来进行实现的,这是因为在图的更新中,用邻接矩阵进行更新所占用的时间开销相对大,二是因为领接矩阵占用的空间大(N方&am…...

构建中国人自己的私人GPT
创作不易,请大家多鼓励支持。 在现实生活中,很多人的资料是不愿意公布在互联网上的,但是我们又要使用人工智能的能力帮我们处理文件、做决策、执行命令那怎么办呢?于是我们构建自己或公司的私人GPT变得非常重要。 先看效果 一、…...

添加气泡与菜单
目录 1、添加气泡 1.1、文本提示气泡 1.2、带按钮的提示气泡 1.3、自定义气泡 2、菜单 2.1、创建默认样式的菜单 2.2、创建自定义样式的菜单 1、添加气泡 Popup属性可绑定在组件上显示气泡弹窗提示,设置弹窗内容、交互逻辑和显示状态。主要用于…...

python代码练习:双指针法
题目一:移除元素 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不…...

C++系列十七:访问控制符
访问权限控制符 一、public访问权限二、private访问权限三、protected访问权限 在C中,访问权限控制符用于限制类成员的访问权限,主要包括public、private和protected三种。这些访问权限控制符用于控制类成员的访问级别,从而保证数据的封装性和…...

postgresql 最简主从配置
实验目的 配置一个最简的主从环境,了解基本的主从配置。 环境参数 操作系统CentOS Linux release 7.9.2009 (Core)数据库版本PostgreSQL 10.23主库端口15431备库端口15432 因为只是做实验,所以主备库放在同一台机器上,仅通过端口区分主备…...

ubuntu 安装 anaconda
ubuntu 安装 anaconda 下载 wget https://repo.anaconda.com/archive/Anaconda3-2023.09-0-Linux-x86_64.sh安装 bash Anaconda3-2023.09-0-Linux-x86_64.sh2.1 回车继续 2.2 许可协议 输入 q 退出阅读许可协议 2.3 输入 yes 接受 许可协议 2.4 设置 anaconda 安装位置 如不需…...

DOM 被劫持
文档对象模型(DOM)充当着 HTML 和 JavaScript 之间的接口,搭建起静态内容与动态交互之间的桥梁,对现代 Web 开发而言,DOM 的作用不可或缺。 然而,DOM 也有一个致命的陷阱 —— DOM 劫持。DOM 劫持是指当 H…...

PIG框架学习2——资源服务器的配置详解
一、前言 1、pig资源服务器的配置 Spring Security oauth2相关的依赖是在pigx-common-security模块中引入的,其他模块需要进行token鉴权的,需要在微服务中引入pigx-common-security模块的依赖,从而间接引入相关的Spring security oauth2依赖…...

vue+element ui实现图片上传并拖拽进行图片排序
用到的技术栈: vue2element Uivue-dragging 如何使用: 第一步: 安装 npm install awe-dnd --save第二步: 引入 main.js 文件 // 引入组件 import VueDND from awe-dnd // 添加至全局 Vue.use(VueDND)具体项目代码 <el-form-item label"封面…...

国产服务器 BIOS下组建RADI不同RAID卡-超详细
国产服务器 长城 组建Raid的方法 说明 大多数国产服务器通用型服务器进入BIOS的都是按DEL键。 9361RAID卡组建方法 在服务器启动过程中,按下DEL键进入BIOS界面。 进入设备管理器,选择AVAGO MegaRAID页签。 3. 进入RAID卡设备,选择Main Me…...

UE4 4.21-4.27使用编辑器蓝图EditorBlueprint方法
在UE4 4.21中,编辑器蓝图(Editor Blueprint)是一个强大的工具,允许开发者扩展和自定义Unreal编辑器的功能。通过编辑器蓝图,我们可以创建自定义的工具和功能,以优化开发流程。 本教程将指导您如何在UE4 4.…...

105、Zero-1-to-3: Zero-shot One Image to 3D Object
简介 官网 使用合成数据集来学习相对摄像机视点的控制,这允许在指定的摄像机变换下生成相同对象的新图像,用于从单个图像进行三维重建的任务。 实现流程 输入图像 x ∈ R H W 3 x \in \R^{H \times W \times 3} x∈RHW3,所需视点的相…...

scala 安装和创建项目
Scala,一种可随您扩展的编程语言:从小型脚本到大型多平台应用程序。Scala不是Java的扩展,但它完全可以与Java互操作。在编译时,Scala文件将转换为Java字节码并在JVM(Java虚拟机)上运行。Scala被设计成面向对…...

Python办公自动化 – 自动化文本翻译和Oracle数据库操作
Python办公自动化 – 自动化文本翻译和Oracle数据库操作 以下是往期的文章目录,需要可以查看哦。 Python办公自动化 – Excel和Word的操作运用 Python办公自动化 – Python发送电子邮件和Outlook的集成 Python办公自动化 – 对PDF文档和PPT文档的处理 Python办公自…...

如何在Win10电脑接收苹果手机日程提醒呢?
有很多小伙伴手机使用的是iPhone苹果手机,但办公电脑使用的win10系统的电脑,这时候如果想要在win10电脑上同步接收苹果手机上设置的日程提醒,该怎么操作呢?如何在win10电脑接收苹果手机日程提醒呢? 如果你设置的日程提…...

227.【2023年华为OD机试真题(C卷)】小明找位置(二分查找-JavaPythonC++JS实现)
🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(Java&Python&C++&JS分别实现),详细代码讲解,助你深入学习,深度掌握! 文章目录 一. 题目-小明找位置二.解题思路三.题解代码Python题解代…...

【现代密码学】笔记3.4-3.7--构造安全加密方案、CPA安全、CCA安全 《introduction to modern cryphtography》
【现代密码学】笔记3.4-3.7--构造安全加密方案、CPA安全、CCA安全 《introduction to modern cryphtography》 写在最前面私钥加密与伪随机性 第二部分流加密与CPA多重加密 CPA安全加密方案CPA安全实验、预言机访问(oracle access) 操作模式伪随机函数PR…...

服务器带宽有什么用? 带宽不足怎么办?
服务器带宽是指服务器能够接收和传输数据的速率,通常以每秒传输的数据量来衡量。它是支持特定应用服务器网络和因特网(Internet)访问的单一网络线路,对网络速度、响应时间、应用程序处理速度等方面都有影响。 服务器带宽有什么作…...

Alphafold2蛋白质结构预测AI工作站配置推荐
AlphaFold2计算特点 蛋白质三维结构预测是一项计算量非常巨大的任务,科学家多年的探索研究,形成了X射线晶体学法、核磁共振法、冷冻电镜等。 2021年底,谷歌的DeepMind团队的采用人工智能方法的AlphaFold2算法在生物界引起了极大的轰动…...