查看原文
其他

DuckDB中Catalog与Schema在duckdb_fdw有啥用?

alitrack alitrack 2023-12-18

最近 duckdb_fdw 增加了对 Catalog 和 Schema 的支持,今天就探讨下 DuckDB 的 Catalog 与 Schema,以及它在 duckdb_fdw 里的重要作用。

数据库中 Catalog,Schema,Table 和 Column 的关系

解释:

  • Catalog(目录): 表示整个数据库或数据库管理系统。一个数据库服务器可以包含多个数据库,每个数据库都有自己的 Catalog。
  • Schema(模式): 在一个数据库中,Schema 用于组织和分类数据库对象,如表、视图、存储过程等。一个 Schema 可以包含多个表。
  • Table(表): 表示实际存储数据的地方。一个 Schema 可以包含多个表,每个表有自己的列。
  • Column(列): 表示表中的字段,定义了表中存储的数据的属性。每个表可以有多个列。

这个层次结构表明,一个数据库中可以包含多个 Schema,每个 Schema 可以包含多个表,而每个表可以包含多个列。这种结构有助于组织和管理数据库中的数据,并提供了一定程度的隔离和命名空间。

让我们和熟悉的 Excel 来做个对比来加深理解,

一个目录下可能有 0 到多个 Excel 文件,一个 Excel 文件可能有 1 到多个 Sheet,一个 sheet 可能有多个列。

Catalog

DuckDB 里执行如下语句的时候第一列是table_catalog

SELECT * FROM information_schema.tables;


table_catalog 列表示表所属的数据库目录。在大多数数据库中,数据库目录通常是数据库的名称。

另外发现这个 table_catalog 和访问的数据库文件名保持一致(duckdb允许attach时候设置别名),如果使用内存数据库,则为memory

运行 duckdb CLI

./duckdb default.db

查看系统视图information_schema.tables

information_schema.tables系统视图提供了一种更加标准化的方式来获取关于数据库表(包括视图)的元数据。
当然也可以使用duckdb_tables,它返回的结果集包含一些在information_schema.tables中未包含的列。

SELECT table_catalog
,table_schema
,table_name,
table_type
FROM information_schema.tables;

返回

┌───────────────┬──────────────┬────────────┬────────────┐
│ table_catalog │ table_schema │ table_name │ table_type │
│    varchar    │   varchar    │  varchar   │  varchar   │
├────────────────────────────────────────────────────────┤
│                         0 rows                         │
└────────────────────────────────────────────────────────┘

让我们创建第一个表,

CREATE TABLE customer (
    c_custkey int8 NULL,
    c_name varchar NULL,
    c_address varchar NULL,
    c_nationkey int8 NULL,
    c_phone varchar NULL,
    c_acctbal numeric NULL,
    c_mktsegment varchar NULL,
    c_comment varchar NULL
);

添加一个新的库

ATTACH '/Users/m2max/temp/duckdb0' AS sf10;

ATTACH 语句将一个新的数据库文件添加到目录中,可以从中读取和写入数据。

再查看下系统视图,

SELECT table_catalog
,table_schema
,table_name,
table_type
FROM information_schema.tables;
┌───────────────┬──────────────┬────────────┬────────────┐
│ table_catalog │ table_schema │ table_name │ table_type │
│    varchar    │   varchar    │  varchar   │  varchar   │
├───────────────┼──────────────┼────────────┼────────────┤
│ default       │ main         │ customer   │ BASE TABLE │
│ default       │ main         │ t1         │ BASE TABLE │
│ sf10          │ main         │ customer   │ VIEW       │
│ sf10          │ main         │ orders     │ VIEW       │
│ sf10          │ main         │ part       │ VIEW       │
│ sf10          │ main         │ supplier   │ VIEW       │
│ sf10          │ main         │ region     │ VIEW       │
│ sf10          │ main         │ nation     │ VIEW       │
│ sf10          │ main         │ partsupp   │ VIEW       │
│ sf10          │ main         │ lineitem   │ VIEW       │
├───────────────┴──────────────┴────────────┴────────────┤
│ 10 rows                                      4 columns │
└────────────────────────────────────────────────────────┘

sf10 catalog 中有 8 张视图(我用于测试 TPCH_sf10 的例子)
同时注意 customer 表有 2 个,一个在 catalog default 中,一个在 sf10 中

查看默认 Catalog

SELECT current_catalog();
┌───────────────────┐
│ current_catalog() │
│      varchar      │
├───────────────────┤
│ default           │
└───────────────────┘

查询默认 Catalog 的 main Schema 的 customer 表

SELECT * FROM customer LIMIT 3;
┌───────────┬─────────┬───────────┬─────────────┬─────────┬───────────────┬──────────────┬───────────┐
│ c_custkey │ c_name  │ c_address │ c_nationkey │ c_phone │   c_acctbal   │ c_mktsegment │ c_comment │
│   int64   │ varchar │  varchar  │    int64    │ varchar │ decimal(18,3) │   varchar    │  varchar  │
├────────────────────────────────────────────────────────────────────────────────────────────────────┤
│                                               0 rows                                               │
└────────────────────────────────────────────────────────────────────────────────────────────────────┘

切换默认 Catalog 为 sf10,

SET SEARCH_PATH TO 'sf10,default';

查看默认 Catalog

SELECT current_catalog();
┌───────────────────┐
│ current_catalog() │
│      varchar      │
├───────────────────┤
│ sf10              │
└───────────────────┘
SELECT c_name FROM customer LIMIT 3;
┌────────────────────┐
│       c_name       │
│      varchar       │
├────────────────────┤
│ Customer#000422881 │
│ Customer#000422882 │
│ Customer#000422883 │
└────────────────────┘

上面 SQL 等价于

SELECT sf10.main.c_name FROM customer LIMIT 3;

包含了 catalog,schema,表名,接下来我们就说下 Schema。

Schema

 

USE default;
CREATE SCHEMA x;

再 SCHEMA x 下创建一张 customer 表

CREATE TABLE default.x.customer as SELECT * FROM customer LIMIT 2;

这个时候如果再执行

SELECT table_catalog
,table_schema
,table_name,
table_type
FROM information_schema.tables;

会发现有三个 customer 表,属于不同的 catalog 和 schema。

┌───────────────┬──────────────┬────────────┬────────────┐
│ table_catalog │ table_schema │ table_name │ table_type │
│    varchar    │   varchar    │  varchar   │  varchar   │
├───────────────┼──────────────┼────────────┼────────────┤
│ default       │ main         │ customer   │ BASE TABLE │
│ default       │ x            │ customer   │ BASE TABLE │
│ sf10          │ main         │ customer   │ VIEW       │
│ sf10          │ main         │ orders     │ VIEW       │
│ sf10          │ main         │ part       │ VIEW       │
│ sf10          │ main         │ supplier   │ VIEW       │
│ sf10          │ main         │ region     │ VIEW       │
│ sf10          │ main         │ nation     │ VIEW       │
│ sf10          │ main         │ partsupp   │ VIEW       │
│ sf10          │ main         │ lineitem   │ VIEW       │
├───────────────┴──────────────┴────────────┴────────────┤
│ 10 rows                                      4 columns │
└────────────────────────────────────────────────────────┘

Catalog 和 Schema 在 duckdb_fdw 中的应用。

IMPORT FOREIGN SCHEMA public  LIMIT TO(customer) FROM SERVER DuckDB_server INTO public;

等价于

CREATE FOREIGN TABLE customer (
    c_custkey int8 NULL,
    c_name varchar NULL,
    c_address varchar NULL,
    c_nationkey int8 NULL,
    c_phone varchar NULL,
    c_acctbal numeric NULL,
    c_mktsegment varchar NULL,
    c_comment varchar NULL
) OPTIONS (table 'default.main.customer');

就是说它导入的是当前数据库,main schema 的 customer,
如果我想使用IMPORT FOREIGN SCHEMA 导入的是 x schema 里的 customer 呢?

IMPORT FOREIGN SCHEMA x  LIMIT TO(customer) FROM SERVER DuckDB_server INTO public;

但如果我想导入的是 sf10 catalog 的表呢?

# attach
SELECT duckdb_execute('duckdb_server','ATTACH ''/Users/m2max/temp/duckdb0'' AS sf10 ;');
# 修改catlog优先访问顺序
SELECT duckdb_execute('duckdb_server','SET SEARCH_PATH ''sf10,memory''');

接下来执行

IMPORT FOREIGN SCHEMA public FROM SERVER DuckDB_server INTO public;

就可以把 sf10(duckdb0)main schema 里的所有表都导入成功了。

当然如果之前导入过 customer,会因为重复而报错。


继续滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存