java
This commit is contained in:
		
							
								
								
									
										118
									
								
								java/Optional正确的使用方法.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								java/Optional正确的使用方法.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
				
			|||||||
 | 
					已剪辑自: https://blog.kaaass.net/archives/764
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Optional 是 Java8 提供的为了解决 null 安全问题的一个 API。善用 Optional 可以使我们代码中很多繁琐、丑陋的设计变得十分优雅。这篇文章是建立在你对 Optional 的用法有一定了解的基础上的,如果你还不太了解 Optional,可以先去看看相关教程,或者查阅 [Java 文档](http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html)。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					使用 Optional,我们就可以把下面这样的代码进行改写。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```java
 | 
				
			||||||
 | 
					public static String getName(User u) {
 | 
				
			||||||
 | 
					   if (u == null || u.name == null)
 | 
				
			||||||
 | 
					     return "Unknown";
 | 
				
			||||||
 | 
					   return u.name;
 | 
				
			||||||
 | 
					 } 
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					不过,千万不要改写成这副样子。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```Java
 | 
				
			||||||
 | 
					ublic static String getName(User u) {
 | 
				
			||||||
 | 
					   Optional<User> user = Optional.ofNullable(u);
 | 
				
			||||||
 | 
					   if (!user.isPresent())
 | 
				
			||||||
 | 
					     return "Unknown";
 | 
				
			||||||
 | 
					   return user.get().name;
 | 
				
			||||||
 | 
					 } 
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					这样改写非但不简洁,而且其操作还是和第一段代码一样。无非就是用 isPresent 方法来替代 u==null。这样的改写并不是 Optional 正确的用法,我们再来改写一次。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```java
 | 
				
			||||||
 | 
					public static String getName(User u) {
 | 
				
			||||||
 | 
					   return Optional.ofNullable(u)
 | 
				
			||||||
 | 
					           .map(user->user.name)
 | 
				
			||||||
 | 
					           .orElse("Unknown");
 | 
				
			||||||
 | 
					 } 
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					这样才是正确使用 Optional 的姿势。那么按照这种思路,我们可以安心的进行链式调用,而不是一层层判断了。看一段代码:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```java
 | 
				
			||||||
 | 
					public static String getChampionName(Competition comp) throws IllegalArgumentException {
 | 
				
			||||||
 | 
					   if (comp != null) {
 | 
				
			||||||
 | 
					     CompResult result = comp.getResult();
 | 
				
			||||||
 | 
					     if (result != null) {
 | 
				
			||||||
 | 
					       User champion = result.getChampion();
 | 
				
			||||||
 | 
					       if (champion != null) {
 | 
				
			||||||
 | 
					         return champion.getName();
 | 
				
			||||||
 | 
					       }
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					   throw new IllegalArgumentException("The value of param comp isn't available.");
 | 
				
			||||||
 | 
					 } 
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					由于种种原因(比如:比赛还没有产生冠军、方法的非正常调用、某个方法的实现里埋藏的大礼包等等),我们并不能开心的一路 comp.getResult().getChampion().getName() 到底。而其他语言比如 kotlin,就提供了在语法层面的操作符加持:comp?.getResult()?.getChampion()?.getName()。所以讲道理在 Java 里我们怎么办!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					让我们看看经过 Optional 加持过后,这些代码会变成什么样子。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```java
 | 
				
			||||||
 | 
					public static String getChampionName(Competition comp) throws IllegalArgumentException {
 | 
				
			||||||
 | 
					   return Optional.ofNullable(comp)
 | 
				
			||||||
 | 
					       .map(Competition::getResult) // 相当于c -> c.getResult(),下同
 | 
				
			||||||
 | 
					       .map(CompResult::getChampion)
 | 
				
			||||||
 | 
					       .map(User::getName)
 | 
				
			||||||
 | 
					       .orElseThrow(()->new IllegalArgumentException("The value of param comp isn't available."));
 | 
				
			||||||
 | 
					 } 
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					这就很舒服了。Optional 给了我们一个真正优雅的 Java 风格的方法来解决 null 安全问题。虽然没有直接提供一个操作符写起来短,但是代码看起来依然很爽很舒服。更何况 ?. 这样的语法好不好看还见仁见智呢。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					还有很多不错的使用姿势,比如字符串为空则不打印可以这么写:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```java
 | 
				
			||||||
 | 
					string.ifPresent(System.out::println);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Optional 的魅力还不止于此,Optional 还有一些神奇的用法,比如 Optional 可以用来检验参数的合法性。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public void setName(String name) throws IllegalArgumentException {
 | 
				
			||||||
 | 
					   this.name = Optional.ofNullable(name)
 | 
				
			||||||
 | 
					             .filter(User::isNameValid)
 | 
				
			||||||
 | 
					             .orElseThrow(()->new IllegalArgumentException("Invalid username."));
 | 
				
			||||||
 | 
					 } 
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					这样写参数合法性检测,应该足够优雅了吧。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2019-10-13 补充 Optional 的本质,提出若干应用建议。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					不过这还没完,上面的两个例子其实还不能完全反应出 Optional 的设计意图。事实上,我们应该更进一步,减少 Optional.ofNullable 的使用。为什么呢?因为 Optional 是被设计成用来代替 null 以表示不确定性的,换句话说,只要一段代码可能产生 null,那它就可以返回 Optional。而我们选择用 Optional 代替 null 的原因,是 Optional 提供了一个把**若干依赖前一步结果**的处理结合在一起的途径。举个例子,在我们调用一个网站的登录接口的时候,大概会有以下的步骤:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. 发送 HTTP 请求,得到返回。
 | 
				
			||||||
 | 
					2. (依赖:接口的返回)解析返回,如将 Json 文本形式的返回结果转化为对象形式。
 | 
				
			||||||
 | 
					3. (依赖:解析的结果)判断结果是否成功。
 | 
				
			||||||
 | 
					4. (依赖:若成功调用的结果)取得鉴权令牌。
 | 
				
			||||||
 | 
					5. (依赖:获得的令牌)进行处理。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					其中,第 2-5 步的每一个步骤都依赖于前一个步骤,而前一个步骤传递过来的数据都具不确定性(有可能是 null)。所以,我们可以把它们接受的数据都设计成 Optional。第 1-4 步每一个步骤的结果也具备不确定性,所以我们也把它们的结果设计成 Optional。最后到了第 5 步,我们终于要对一切的结果进行处理了:如果成功获得令牌就存储,失败就提示用户。所以这一步,我们采用如 orElse 之类的方法来**消除**不确定性。于是我们最后的设计就可以是:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. 结果 String(可能是 null) **==** **包装** **==>** Optional<String>
 | 
				
			||||||
 | 
					2. Optional<String> **==** **解析** **==>** Optional<Json对象>
 | 
				
			||||||
 | 
					3. Optional<Json对象> **== Filter** **判断成功** **==>** Optional<Json对象>
 | 
				
			||||||
 | 
					4. Optional<Json对象> **==** **取鉴权令牌** **==>** Optional<AuthToken>
 | 
				
			||||||
 | 
					5. 对 Optional<AuthToken> 进行处理,消除 Optional
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Optional 就像一个处理不确定性的管道,我们在一头丢进一个可能是 null 的东西(接口返回结果),经过层层处理,最后消除不确定性。**Optional 在过程中保留了不确定性,从而把对 null 的处理移到了若干次操作的最后,以减少出现 NPE 错误的可能。**于是,Optional 应用的建议也呼之欲出了:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. 适用于层级处理(依赖上一步操作)的场合。
 | 
				
			||||||
 | 
					2. 产生对象的方法若可能返回 null,可以用 Optional 包装。
 | 
				
			||||||
 | 
					3. 尽可能延后处理 null 的时机,在过程中使用 Optional 保留不确定性。
 | 
				
			||||||
 | 
					4. 尽量避免使用 Optional 作为字段类型。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					最后说句题外话,这种依赖上一步的操作也叫 Continuation。而 Optional 的这种接受并组合多个 Continuation 的设计风格就是 Continuation-passing style(CPS)。
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 参考资料
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					使用 Java8 Optional 的正确姿势 – 隔叶黄莺 Unmi Blog (https://unmi.cc/proper-ways-of-using-java8-optional/)
 | 
				
			||||||
@@ -131,7 +131,7 @@ public class MDCRunnable implements Runnable {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
接着,我们需要对main函数里创建的Runnable实现类进行装饰:
 | 
					接着,我们需要对main函数里创建的Runnable实现类进行装饰:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```java
 | 
				
			||||||
public class Main {
 | 
					public class Main {
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
   private static final String KEY = "requestId";
 | 
					   private static final String KEY = "requestId";
 | 
				
			||||||
@@ -140,13 +140,13 @@ public class Main {
 | 
				
			|||||||
 
 | 
					 
 | 
				
			||||||
   public static void main(String[] args) {
 | 
					   public static void main(String[] args) {
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
     *// 入口传入请求ID*
 | 
					     // 入口传入请求ID
 | 
				
			||||||
     *MDC.put(KEY, UUID.randomUUID().toString());*
 | 
					     MDC.put(KEY, UUID.randomUUID().toString());
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
     // 主线程打印日志*
 | 
					 | 
				
			||||||
     *logger.debug(*"log in main thread");
 | 
					 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
     *// 异步线程打印日志,用MDCRunnable装饰Runnable*
 | 
					     // 主线程打印日志
 | 
				
			||||||
 | 
					     logger.debug(*"log in main thread");
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					     // 异步线程打印日志,用MDCRunnable装饰Runnable
 | 
				
			||||||
     new Thread(new MDCRunnable(new Runnable() {
 | 
					     new Thread(new MDCRunnable(new Runnable() {
 | 
				
			||||||
       @Override
 | 
					       @Override
 | 
				
			||||||
       public void run() {
 | 
					       public void run() {
 | 
				
			||||||
@@ -154,8 +154,8 @@ public class Main {
 | 
				
			|||||||
       }
 | 
					       }
 | 
				
			||||||
     })).start();
 | 
					     })).start();
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
     *// 异步线程池打印日志,用MDCRunnable装饰Runnable*
 | 
					     // 异步线程池打印日志,用MDCRunnable装饰Runnable
 | 
				
			||||||
     *EXECUTOR.execute(*new MDCRunnable(new Runnable() {
 | 
					     EXECUTOR.execute(*new MDCRunnable(new Runnable() {
 | 
				
			||||||
       @Override
 | 
					       @Override
 | 
				
			||||||
       public void run() {
 | 
					       public void run() {
 | 
				
			||||||
         logger.debug("log in other thread pool");
 | 
					         logger.debug("log in other thread pool");
 | 
				
			||||||
@@ -163,12 +163,12 @@ public class Main {
 | 
				
			|||||||
     }));
 | 
					     }));
 | 
				
			||||||
     EXECUTOR.shutdown();
 | 
					     EXECUTOR.shutdown();
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
     *// 出口移除请求ID*
 | 
					     // 出口移除请求ID
 | 
				
			||||||
     *MDC.remove(KEY);*
 | 
					     MDC.remove(KEY);
 | 
				
			||||||
 *
 | 
					 
 | 
				
			||||||
   }*
 | 
					   }
 | 
				
			||||||
 *
 | 
					 
 | 
				
			||||||
 }*
 | 
					 }
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										149
									
								
								postgresql_and_edb/postgresql系统表.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								postgresql_and_edb/postgresql系统表.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
				
			|||||||
 | 
					已剪辑自: https://blog.csdn.net/yang_z_1/article/details/112270447
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 版本11.5 
 | 
				
			||||||
 | 
					 系统表是关系型数据库存放模式元数据的地方,比如表和列的信息,以及内部统计信息等。PostgreSQL的系统表就是普通表。你可以删除并重建这些表、增加列、插入和更新数值, 然后彻底把你的系统搞垮。 通常情况下,我们不应该手工修改系统表,通常有 SQL 命令可以做这些事情。(例如, CREATE DATABASE 向 pg_database 表插入一行 — 并且实际上在磁盘上创建该数据库。)。 有几种特别深奥的操作例外,但是随着时间的流逝其中的很多也可以用 SQL 命令来完成,因此对系统表直接修改的需求也越来越小。 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 一 系统表总览
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					系统表名用途
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					|                         |                                            |
 | 
				
			||||||
 | 
					| ----------------------- | ------------------------------------------ |
 | 
				
			||||||
 | 
					| pg_aggregate            | 聚集函数                                   |
 | 
				
			||||||
 | 
					| pg_am                   | 索引访问方法                               |
 | 
				
			||||||
 | 
					| pg_amop                 | 访问方法操作符                             |
 | 
				
			||||||
 | 
					| pg_amproc               | 访问方法支持过程                           |
 | 
				
			||||||
 | 
					| pg_attrdef              | 列默认值                                   |
 | 
				
			||||||
 | 
					| pg_attribute            | 表列 (  “属性” )                           |
 | 
				
			||||||
 | 
					| pg_authid               | 认证标识符(角色)                         |
 | 
				
			||||||
 | 
					| pg_auth_members         | 认证标识符成员关系                         |
 | 
				
			||||||
 | 
					| pg_cast                 | 转换(数据类型转换)                       |
 | 
				
			||||||
 | 
					| pg_class                | 表、索引、序列、视图  (“关系”)           |
 | 
				
			||||||
 | 
					| pg_collation            | 排序规则(locale信息)                     |
 | 
				
			||||||
 | 
					| pg_constraint           | 检查约束、唯一约束、主键约束、外键约束     |
 | 
				
			||||||
 | 
					| pg_conversion           | 编码转换信息                               |
 | 
				
			||||||
 | 
					| pg_database             | 本数据库集簇中的数据库                     |
 | 
				
			||||||
 | 
					| pg_db_role_setting      | 每角色和每数据库的设置                     |
 | 
				
			||||||
 | 
					| pg_default_acl          | 对象类型的默认权限                         |
 | 
				
			||||||
 | 
					| pg_depend               | 数据库对象间的依赖                         |
 | 
				
			||||||
 | 
					| pg_description          | 数据库对象上的描述或注释                   |
 | 
				
			||||||
 | 
					| pg_enum                 | 枚举标签和值定义                           |
 | 
				
			||||||
 | 
					| pg_event_trigger        | 事件触发器                                 |
 | 
				
			||||||
 | 
					| pg_extension            | 已安装扩展                                 |
 | 
				
			||||||
 | 
					| pg_foreign_data_wrapper | 外部数据包装器定义                         |
 | 
				
			||||||
 | 
					| pg_foreign_server       | 外部服务器定义                             |
 | 
				
			||||||
 | 
					| pg_foreign_table        | 外部表信息                                 |
 | 
				
			||||||
 | 
					| pg_index                | 索引信息                                   |
 | 
				
			||||||
 | 
					| pg_inherits             | 表继承层次                                 |
 | 
				
			||||||
 | 
					| pg_init_privs           | 对象初始特权                               |
 | 
				
			||||||
 | 
					| pg_language             | 编写函数的语言                             |
 | 
				
			||||||
 | 
					| pg_largeobjec           | t大对象的数据页                            |
 | 
				
			||||||
 | 
					| pg_largeobject          | _metadata大对象的元数据                    |
 | 
				
			||||||
 | 
					| pg_namespace            | 模式                                       |
 | 
				
			||||||
 | 
					| pg_opclass              | 访问方法操作符类                           |
 | 
				
			||||||
 | 
					| pg_operator             | 操作符                                     |
 | 
				
			||||||
 | 
					| pg_opfamily             | 访问方法操作符族                           |
 | 
				
			||||||
 | 
					| pg_partitioned_table    | 有关表的分区键的信息                       |
 | 
				
			||||||
 | 
					| pg_pltemplate           | 过程语言的模板数据                         |
 | 
				
			||||||
 | 
					| pg_policy               | 行安全策略                                 |
 | 
				
			||||||
 | 
					| pg_proc                 | 函数和过程                                 |
 | 
				
			||||||
 | 
					| pg_publication          | 逻辑复制的发布                             |
 | 
				
			||||||
 | 
					| pg_publication_rel      | 与发布映射的关系                           |
 | 
				
			||||||
 | 
					| pg_range                | 范围类型的信息                             |
 | 
				
			||||||
 | 
					| pg_replication_origin   | 已注册的复制源                             |
 | 
				
			||||||
 | 
					| pg_rewrite              | 查询重写规则                               |
 | 
				
			||||||
 | 
					| pg_seclabel             | 数据库对象上的安全标签                     |
 | 
				
			||||||
 | 
					| pg_sequence             | 有关序列的信息                             |
 | 
				
			||||||
 | 
					| pg_shdepend             | 共享对象上的依赖                           |
 | 
				
			||||||
 | 
					| pg_shdescription        | 共享对象上的注释                           |
 | 
				
			||||||
 | 
					| pg_shseclabel           | 共享数据库对象上的安全标签                 |
 | 
				
			||||||
 | 
					| pg_statistic            | 规划器统计                                 |
 | 
				
			||||||
 | 
					| pg_statistic_ext        | 扩展的规划器统计                           |
 | 
				
			||||||
 | 
					| pg_subscription         | 逻辑复制订阅                               |
 | 
				
			||||||
 | 
					| pg_subscription_rel     | 订阅的关系状态                             |
 | 
				
			||||||
 | 
					| pg_tablespace           | 本数据库集簇内的表空间                     |
 | 
				
			||||||
 | 
					| pg_transform            | 转换(将数据类型转换为过程语言需要的形式) |
 | 
				
			||||||
 | 
					| pg_trigger              | 触发器                                     |
 | 
				
			||||||
 | 
					| pg_ts_config            | 文本搜索配置                               |
 | 
				
			||||||
 | 
					| pg_ts_config_map        | 文本搜索配置的记号映射                     |
 | 
				
			||||||
 | 
					| pg_ts_dict              | 文本搜索字典                               |
 | 
				
			||||||
 | 
					| pg_ts_parser            | 文本搜索分析器                             |
 | 
				
			||||||
 | 
					| pg_ts_template          | 文本搜索模板                               |
 | 
				
			||||||
 | 
					| pg_type                 | 数据类型                                   |
 | 
				
			||||||
 | 
					| pg_user_mapping         | 将用户映射到外部服务器                     |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 二 常用系统表
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 1.pg_class
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**pg_class 记录表和几乎所有具有列或者像表的东西。 这包括索引(但还要参见 pg_index )、序列 (pg_sequence )、视图、物化视图、组合类型和 TOAST 表**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					名称类型引用描述
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					|                     |              |                                                              |                                                              |
 | 
				
			||||||
 | 
					| ------------------- | ------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
 | 
				
			||||||
 | 
					| oid                 | oid          |                                                              | 行标识符(隐藏属性,必须被显式选择才会显示)                 |
 | 
				
			||||||
 | 
					| relname             | name         |                                                              | 表、索引、视图等的名字                                       |
 | 
				
			||||||
 | 
					| relnamespace        | oid          | pg_namespace.oid                                             | 包含该关系的名字空间的  OID                                  |
 | 
				
			||||||
 | 
					| reltype             | oid          | pg_type.oid                                                  | 可能存在的表行类型所对应数据类型的OID(对索引为0,索引没有  pg_type 项) |
 | 
				
			||||||
 | 
					| reloftype           | oid          | pg_type.oid                                                  | 对于有类型的表,为底层组合类型的OID,对于其他所有关系为  0   |
 | 
				
			||||||
 | 
					| relowner            | oid          | pg_authid.oid                                                | 关系的拥有者                                                 |
 | 
				
			||||||
 | 
					| relam               | oid          | pg_am.oid                                                    | 如果这是一个索引,表示索引使用的访问方法(B树、哈希等)      |
 | 
				
			||||||
 | 
					| relfilenode         | oid          | 该关系的磁盘文件的名字,0表示这是一个“映射”关系,其磁盘文件名取决于低层状态 |                                                              |
 | 
				
			||||||
 | 
					| reltablespace       | oid          | pg_tablespace.oid                                            | 该关系所存储的表空间。如果为0,使用数据库的默认表空间。(如果关系无磁盘文件时无意义) |
 | 
				
			||||||
 | 
					| relpages            | int4         |                                                              | 该表磁盘表示的尺寸,以页面计(页面尺寸为                     |
 | 
				
			||||||
 | 
					| reltuples           | float4       |                                                              | 表中的行数。这只是一个由规划器使用的估计值。它被VACUUM、ANALYZE以及一些DDL命令(如CREATEINDEX)所更新。 |
 | 
				
			||||||
 | 
					| relallvisible       | int4         |                                                              | 在表的可见性映射表中被标记为全可见的页数。这只是一个由规划器使用的估计值。它被VACUUM、aNALYZE以及一些DDL命令(如CREATEINDEX)所更新。 |
 | 
				
			||||||
 | 
					| reltoastrelid       | oid          | pg_class.oid                                                 | 与该表相关联的TOAST表的OID,如果没有则为0。TOAST表将大属性“线系统表外”存储在一个二级表中。 |
 | 
				
			||||||
 | 
					| relhasindex         | bool         |                                                              | 如果这是一个表并且其上建有(或最近建有)索引则为真           |
 | 
				
			||||||
 | 
					| relisshared         | bool         |                                                              | 如果该表在集簇中的所有数据库间共享则为真。只有某些系统表(如 |
 | 
				
			||||||
 | 
					| relpersistence      | char         |                                                              | p=永久表,u=无日志表,t=临时表                               |
 | 
				
			||||||
 | 
					| relkind             | char         |                                                              | r=普通表,i=索引,S=序列,t=TOAST表,v=视图,m=物化视图,c=组合类型,f=外部表,p=分区表 |
 | 
				
			||||||
 | 
					| relnatts            | int2         |                                                              | 关系中用户列的数目(系统列不计算在内)。                     |
 | 
				
			||||||
 | 
					| relchecks           | int2         |                                                              | 表上 CHECK  约束的数目,                                     |
 | 
				
			||||||
 | 
					| relhasoids          | bool         |                                                              | 如果为关系的每一行生成一个OID则为真                          |
 | 
				
			||||||
 | 
					| relhaspkey          | bool         |                                                              | 如果表有(或曾有)一个主键则为真                             |
 | 
				
			||||||
 | 
					| relhasrules         | bool         |                                                              | 如果表有(或曾有)规则则为真,                               |
 | 
				
			||||||
 | 
					| relhastriggers      | bool         |                                                              | 如果表有(或曾有)触发器则为真,                             |
 | 
				
			||||||
 | 
					| relhassubclass      | bool         |                                                              | 如果表有(或曾有)任何继承子女则为真                         |
 | 
				
			||||||
 | 
					| relrowsecurity      | bool         |                                                              | 如果表上启用了行级安全性则为真,                             |
 | 
				
			||||||
 | 
					| relforcerowsecurity | bool         |                                                              | 如果行级安全性(启用时)也适用于表拥有者则为真,             |
 | 
				
			||||||
 | 
					| relispopulated      | bool         |                                                              | 如果表已被填充则为真(对于所有关系该系统表列都为真,但对于某些物化视图却不是) |
 | 
				
			||||||
 | 
					| relreplident        | char         |                                                              | 用来为行形成“replicaidentity”的列:d=默认(主键,如果存在),n=无,f=所有列i=索引的indisreplident  被设置或者为默认 |
 | 
				
			||||||
 | 
					| relispartition      | bool         |                                                              | 如果表是分区,则为真                                         |
 | 
				
			||||||
 | 
					| relfrozenxid        | xid          |                                                              | 在此之前的所有事务ID在表中已经被替换为一个永久的(“冻结的”  )事务ID。这用于跟踪表是否需要被清理,以便阻止事务ID回卷或者允许pg_xact被收缩。如果该关系不是一个表则为0(InvalidTransactionId)。 |
 | 
				
			||||||
 | 
					| relminmxid          | xid          |                                                              | 在此之前的多事务ID在表中已经被替换为一个事务ID。这被用于跟踪表是否需要被清理,以阻止多事务ID回卷或者允许pg_multixact被收缩。如果关系不是一个表则为0(InvalidMultiXactId)。 |
 | 
				
			||||||
 | 
					| relacl              | aclitem[]    |                                                              | 访问权限                                                     |
 | 
				
			||||||
 | 
					| reloptions          | text[]       |                                                              | 访问方法相关的选项,以“keyword=value”字符串形式              |
 | 
				
			||||||
 | 
					| relpartbound        | pg_node_tree |                                                              | 如果表是分区,则是分区绑定的内部表示形式                     |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### 2 pg_attribute
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**pg_attribute 存储有关表列的信息。数据库中的每一个表的每一个列都恰好在 pg_attribute 中有一行。**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					名字类型引用描述
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					|               |           |                  |                                                              |
 | 
				
			||||||
 | 
					| ------------- | --------- | ---------------- | ------------------------------------------------------------ |
 | 
				
			||||||
 | 
					| attrelid      | oid       | pg_class.oid     | 此列所属的表。                                               |
 | 
				
			||||||
 | 
					| attname       | name      |                  | 列名。                                                       |
 | 
				
			||||||
 | 
					| atttypid      | oid       | pg_type.oid      | 列的数据类型。                                               |
 | 
				
			||||||
 | 
					| attstattarget | int4      |                  | attstattarget控制ANALYZE为这个列设置的统计细节的级别。零值表示不收集统计信息,负数表示使用系统缺省的统计对象。正数值的确切信息是和数据类型相关的。 |
 | 
				
			||||||
 | 
					| attlen        | int2      |                  | 该列所属类型的长度。(pg_type.typlen的拷贝)                   |
 | 
				
			||||||
 | 
					| attnum        | int2      |                  | 列的编号,普通列是从1开始计数的。系统列,如oid,是任意的负数。 |
 | 
				
			||||||
 | 
					| attndims      | int4      |                  | 如果该列是数组,该值表示数组的维数,否则是0。                |
 | 
				
			||||||
 | 
					| attcacheoff   | int4      |                  | 在磁盘上总是-1,但是如果装载入内存中的行描述器中,  它可能会被更新为缓冲在行中列的偏移量。 |
 | 
				
			||||||
 | 
					| atttypmod     | int4      |                  | 表示数据表在创建时提供的类型相关的数据(比如,varchar列的最大长度)。其值对那些不需要atttypmod的类型而言通常为-1。 |
 | 
				
			||||||
 | 
					| attbyval      | bool      |                  | pg_type.typbyval列值的拷贝。                                 |
 | 
				
			||||||
 | 
					| attstorage    | char      |                  | pg_type.typstorage列值的拷贝。                               |
 | 
				
			||||||
 | 
					| attalign      | char      |                  | pg_type.typalign列值的拷贝。                                 |
 | 
				
			||||||
 | 
					| attnotnull    | bool      |                  | 如果该列带有非空约束,则为真,否则为假。                     |
 | 
				
			||||||
 | 
					| atthasdef     | bool      |                  | 该列是否存在缺省值,此时它对应pg_attrdef表里实际定义此值的记录。 |
 | 
				
			||||||
 | 
					| attisdropped  | bool      |                  | 该列是否已经被删除。如果被删除,该列在物理上仍然存在表中,但会被分析器忽略,因此不能再通过SQL访问。 |
 | 
				
			||||||
 | 
					| attislocal    | bool      |                  | 该列是否局部定义在对象中的。                                 |
 | 
				
			||||||
 | 
					| attinhcount   | int4      |                  | 该列所拥有的直接祖先的个数。如果一个列的祖先个数非零,那么它就不能被删除或重命名。 |
 | 
				
			||||||
 | 
					| attcollation  | oid       | pg_collation.oid | 该列被定义的排序规则,如果该列不是一个可排序数据类型则为0。  |
 | 
				
			||||||
 | 
					| attacl        | aclitem[] |                  | 列级访问权限                                                 |
 | 
				
			||||||
 | 
					| attoptions    | text[]    |                  | 属性级选项                                                   |
 | 
				
			||||||
 | 
					| attfdwoptions | text[]    |                  | 属性级的外部数据包装器选项                                   |
 | 
				
			||||||
		Reference in New Issue
	
	Block a user