Databricks 第6篇:Spark SQL 維護資料庫和表

悅光陰發表於2021-01-13

Spark SQL 表的命名方式是db_name.table_name,只有資料庫名稱和資料表名稱。如果沒有指定db_name而直接引用table_name,實際上是引用default 資料庫下的表。在Spark SQL中,資料庫只是指定表檔案儲存的路徑,每個表都可以使用不同的檔案格式來儲存資料,從這個角度來看,可以把database看作是Databricks 表的上層目錄,用於組織資料表及其檔案。

在python語言環境中,可以使用 %sql 切換到SQL命令模式:

%sql

一,管理資料庫

常用的資料庫命令,切換當前的資料庫、顯示資料庫列表、表列表、檢視列表和列資訊:

use db_name
show databases 
show tables [in db_name]
show views [in db_name]
show columns in db_name.table_name

1,建立資料庫

建立資料庫,通過LOCATION 指定資料庫檔案儲存的位置:

CREATE { DATABASE | SCHEMA } [ IF NOT EXISTS ] database_name
    [ LOCATION database_directory ]

LOCATION database_directory:指定儲存資料庫檔案系統的路徑,如果底層的檔案系統中不存在該路徑,那麼需要先建立該目錄。如果未指定LOCATION引數,那麼使用預設的資料倉儲目錄來建立資料庫,預設的資料倉儲目錄是由靜態配置引數spark.sql.warehouse.dir指定的

2,檢視資料庫的描述

{ DESC | DESCRIBE } DATABASE [ EXTENDED ] db_name

extended 選項表示檢視資料庫的擴充套件屬性。

3,刪除資料庫

DROP { DATABASE | SCHEMA } [ IF EXISTS ] dbname [ RESTRICT | CASCADE ]

IF EXISTS:該選項表示在資料庫不存在時,DROP操作不會引發異常。
RESTRICT:該選項表示不能刪除非空資料庫,並在預設情況下啟用。
CASCADE:該選項表示刪除資料庫中所有關聯的表和函式。

二,建立資料表

表有兩種作用域:全域性和本地,全域性表可以在所有的Cluster中引用,而本地表只能在本地的Cluster中引用,被稱作臨時檢視。使用者可以從DBFS中的檔案或儲存在任何受支援資料來源中的資料來填充表。

在建立表時,需要指定儲存表資料的檔案格式,以及表資料檔案儲存的位置。

1,使用資料來源建立表(標準的CREATE TABLE命令)

建立表的語法,注意:如果資料庫中已存在同名的表,則會引發異常。

CREATE TABLE [ IF NOT EXISTS ] [db_name].table_name
    [ ( col_name1 col_type1, ... ) ]
    USING data_source
    [ OPTIONS ( key1=val1, key2=val2, ... ) ]
    [ PARTITIONED BY ( col_name1, col_name2, ... ) ]
    [ CLUSTERED BY ( col_name3, col_name4, ... )
        [ SORTED BY ( col_name [ ASC | DESC ], ... ) ]
        INTO num_buckets BUCKETS ]
    [ LOCATION path ]
    [ AS select_statement ]

引數註釋:

  • IF NOT EXISTS:如果資料庫中已存在同名的表,則不會執行任何操作。
  • USING data_source:用於表的檔案格式,data_source 必須是 TEXT、CSV、JSON、JDBC、PARQUET、ORC、HIVE、DELTA 或 LIBSVM 中的一個,或 org.apache.spark.sql.sources.DataSourceRegister 的自定義實現的完全限定的類名。支援使用 HIVE 建立 Hive SerDe 表。 你可以使用 OPTIONS 子句指定 Hive 特定的 file_format 和 row_format,這是不區分大小寫的字串對映。選項鍵為 FILEFORMAT、INPUTFORMAT、OUTPUTFORMAT、SERDE、FIELDDELIM、ESCAPEDELIM、MAPKEYDELIM 和 LINEDELIM。
  • OPTIONS:用於優化表的行為或配置 HIVE 表的表選項。
  • PARTITIONED BY (col_name1, col_name2, ...):按指定的列對建立的表進行分割槽,將為每個分割槽建立一個目錄。
  • CLUSTERED BY col_name3, col_name4, ...):按照指定的列,把表中的分割槽分割到固定數目的 Bucket中,該選項通常與分割槽操作配合使用。delta格式的檔案不支援該子句。
    • SORTED BY:資料在buckets中的排序方式,預設是升序ASC。
    • INTO num_buckets BUCKETS:bucket是一個優化技術,使用bucket(和bucket 列)來確定資料的分割槽,並避免資料洗牌(data shuffle),使資料變得有序。
  • LOCATION path:用於儲存表資料的目錄,可以指定分散式儲存上的路徑。
  • AS select_statement:使用來自 SELECT 語句的輸出資料填充該表。

2,使用Delta Lake(增量Lake)建立表

使用者可以使用標準的CREATE TABLE命令來建立儲存在delta lake中的表,除了標準的建立delta table的命令之外,還可以使用以下的語法來建立delta表:

CREATE [OR REPLACE] TABLE table_identifier[(col_name1 col_type1 [NOT NULL], ...)]
  USING DELTA
  [LOCATION <path-to-delta-files>]

table_identifier 有兩種格式:

  • [database_name.] table_name: 表的名稱
  • delta.`delta_file_path` :在指定的路徑上建立表,而不在元儲存(metastore)中建立條目。

LOCATION <path-to-delta-files> :如果指定的 LOCATION 已包含增量 lake 中儲存的資料,Delta lake 會執行以下操作:

如果僅指定了表名稱和位置,例如:

CREATE TABLE events
  USING DELTA
  LOCATION '/mnt/delta/events'

Hive 元儲存中的表會自動繼承現有資料的架構、分割槽和表屬性,此功能可用於把資料“匯入”到元儲存(metastore)中。

如果你指定了任何配置(架構、分割槽或表屬性),那麼 Delta Lake 會驗證指定的內容是否與現有資料的配置完全匹配。如果指定的配置與資料的配置並非完全匹配,則 Delta Lake 會引發一個描述差異的異常。

3,建立表的示例

--Use data source
CREATE TABLE student (id INT, name STRING, age INT) USING PARQUET;

--Use data from another table
CREATE TABLE student_copy USING PARQUET
    AS SELECT * FROM student;

--Omit the USING clause, which uses the default data source (parquet by default)
CREATE TABLE student (id INT, name STRING, age INT);

--Create partitioned and bucketed table CREATE TABLE student (id INT, name STRING, age INT) USING PARQUET PARTITIONED BY (age) CLUSTERED BY (Id) INTO 4 buckets;

三,和資料來源的互動

資料來源表的作用類似於指向基礎資料來源的指標,例如,您可以使用JDBC資料來源在Azure Databricks中建立表foo,該表指向MySQL中的表bar。當讀寫表foo時,實際上就是讀寫表bar。

通常,CREATE TABLE會建立一個“指標”,並且必須確保它指向的物件是存在的,一個例外是檔案源,例如Parquet,JSON,如果您未指定LOCATION選項,那麼Azure Databricks會建立一個預設表位置。

對於CREATE TABLE AS SELECT,Azure Databricks使用select查詢的輸出資料來覆蓋(overwrite)底層的資料來源,以確保建立的表包含與輸入查詢完全相同的資料。

四,向表插入資料

使用者可以向表種插入資料,也可以向Spark支援的檔案中插入資料。

1,向表中插入資料

使用INSERT INTO 命令向表中追加資料,不會影響表中的現有資料;使用INSERT OVERWRITE 命令,會覆蓋表中的現有資料。

INSERT INTO [ TABLE ] table_identifier [ partition_spec ]
    { VALUES ( { value | NULL } [ , ... ] ) [ , ( ... ) ] | query }

INSERT OVERWRITE [ TABLE ] table_identifier [ partition_spec [ IF NOT EXISTS ] ]
    { VALUES ( { value | NULL } [ , ... ] ) [ , ( ... ) ] | query }

引數註釋:

  • table_identifier:[database_name.] table_name:表名稱,可選擇使用資料庫名稱進行限定。delta.<路徑到表> :現有增量表的位置。
  • partition_spec:一個可選引數,用於指定分割槽的鍵/值對的逗號分隔列表。語法:PARTITION ( partition_col_name = partition_col_val [ , ... ] )
  • 值 ( {value |NULL} [,...] ) [, ( ... ) ]:要插入的值。 顯式指定的值或 NULL 。 使用逗號分隔子句中的每個值。 您可以指定多個值集來插入多個行。
  • query:生成要插入的行的查詢,可用的查詢格式:SELECT語句、TABLE語句、FROM語句 

舉個例子,建立表之後,通過VALUES子句向表中插入少量的值,也可以通過 SELECT 子句、TABLE和FROM向表中批量插入資料。

CREATE TABLE students (name VARCHAR(64), address VARCHAR(64), student_id INT)
    USING PARQUET PARTITIONED BY (student_id);

-- VALUES
INSERT INTO students VALUES
    ('Bob Brown', '456 Taylor St, Cupertino', 222222),
    ('Cathy Johnson', '789 Race Ave, Palo Alto', 333333);

-- SELECT
INSERT INTO students PARTITION (student_id = 444444)
    SELECT name, address FROM persons WHERE name = "Dora Williams";

-- TABLE
INSERT INTO students TABLE visiting_students;

-- FROM
INSERT INTO students
     FROM applicants SELECT name, address, id applicants WHERE qualified = true;

2,向檔案中插入資料

使用給定的Spark檔案格式用新值覆蓋目錄中的現有資料,也就是說,向目錄中插入資料時,只能用新資料覆蓋現有的資料:

INSERT OVERWRITE [ LOCAL ] DIRECTORY [ directory_path ]
    USING file_format [ OPTIONS ( key = val [ , ... ] ) ]
    { VALUES ( { value | NULL } [ , ... ] ) [ , ( ... ) ] | query }

引數註釋:

  • directory_path:目標目錄,還可以使用在中指定 OPTIONS path 。 LOCAL關鍵字用於指定目錄位於本地檔案系統中。
  • file_format:要用於插入的檔案格式。 有效選項包括 TEXT 、 CSV 、 JSON 、 JDBC 、 PARQUET 、ORC、HIVE、LIBSVM,或者自定義實現的完全限定類名 org.apache.spark.sql.execution.datasources.FileFormat 。
  • OPTIONS ( key = val [,...] ):指定用於寫入檔案格式的一個或多個選項。

 示例,使用新資料覆蓋目錄中的資料:

INSERT OVERWRITE DIRECTORY '/tmp/destination'
    USING parquet
    OPTIONS (col1 1, col2 2, col3 'test')
    SELECT * FROM test_table;

INSERT OVERWRITE DIRECTORY
    USING parquet
    OPTIONS ('path' '/tmp/destination', col1 1, col2 2, col3 'test')
    SELECT * FROM test_table;

 

 

參考文件:

SQL reference for Databricks Runtime 7.x

相關文章