Microsoft Fabric workout - pyspark.sql.DataFrameWriter.saveAsTable / pyspark.sql.DataFrameWriter.save

きっとカンタンなことなんんだろうなと思っていても、少しでも疑問に思ったら確かめるだけのことだ。`saveAsTable` と `save`、どう違うの？と。試してわかったことはテーブルのタイプである。

**MANAGED table**
Lakehouse テーブルのソースファイルは、`CREATE TABLE`で自動的に用意され、`DELETE TABLE`でソースファイルも削除される。
**EXTERNAL table**
`CREATE TABLE`でも Lakehouse テーブルのソースファイルは自動的に用意されない。`DELETE TABLE`でもソースファイルは削除されない。

# pyspark.sql.DataFrameWriter.saveAsTable
https://spark.apache.org/docs/3.4.1/api/python/reference/pyspark.sql/api/pyspark.sql.DataFrameWriter.saveAsTable.html
## MANAGED table
```python:PySpark : Runtime 1.2
(spark.range(5)
    .write
    .format("delta")
    .mode("overwrite")
    .saveAsTable("managed_table"))
```
```sql:Spark SQL : Runtime 1.2
CREATE OR REPLACE TABLE managed_table
USING DELTA
AS SELECT * FROM range(5)
```
```json:commitInfo : Runtime 1.2
{
    "commitInfo": {
        "timestamp": 0000000000000,
        "operation": "CREATE OR REPLACE TABLE AS SELECT",
        "operationParameters": {
            "isManaged": "true",
            "description": null,
            "partitionBy": "[]",
            "properties": "{}"
        },
        "isolationLevel": "Serializable",
        "isBlindAppend": false,
        "operationMetrics": {
            "numFiles": "1",
            "numOutputRows": "5",
            "numOutputBytes": "854"
        },
        "tags": {
            "VORDER": "true"
        },
        "engineInfo": "Apache-Spark/3.4.1.5.3-117503204 Delta-Lake/2.4.0.9",
        "txnId": "********-****-****-****-************"
    }
}
```
## EXTERNAL table
```python:PySpark : Runtime 1.2
(spark.range(5)
    .write
    .format("delta")
    .mode("overwrite")
    .saveAsTable(
        "external_table"
        , path="Files/external_table"))
```
```sql:Spark SQL : Runtime 1.2
CREATE OR REPLACE TABLE external_table
USING DELTA
LOCATION "Files/external_table"
AS SELECT * FROM range(5)
```

```python:PySpark : Runtime 1.2
df_metadata = spark.sql("DESCRIBE EXTENDED table_name")
(df_metadata.filter(
    (df_metadata.col_name == "Name")
    | (df_metadata.col_name == "Type")
    | (df_metadata.col_name == "Provider")
).show(truncate=False))
```

|col_name|data_type|comment|
|:--|:--|:--|
|Name|spark_catalog.*`lakehouse_name`*.*`table_name`*||
|Type|MANAGED, EXTERNAL||
|Provider|delta||

```sql:Spark SQL : Runtime 1.2
DROP TABLE IF EXISTS external_table;

CREATE EXTERNAL TABLE external_table
LOCATION "Files/contents";
```
# pyspark.sql.DataFrameWriter.save
https://spark.apache.org/docs/3.4.1/api/python/reference/pyspark.sql/api/pyspark.sql.DataFrameWriter.save.html
## Save contents
```python:PySpark : Runtime 1.2
(spark.range(5)
    .write
    .format("delta")
    .mode("overwrite")
    .save("Files/contents"))
```
## 結果的に MANAGED table
結果的には MANAGED table になる。commitInfo は異なる。
```python:PySpark : Runtime 1.2
(spark.range(5)
    .write
    .format("delta")
    .mode("overwrite")
    .save("Tables/managed_table"))
```
```json:commitInfo : Runtime 1.2
{
    "commitInfo": {
        "timestamp": 0000000000000,
        "operation": "WRITE",
        "operationParameters": {
            "mode": "Overwrite",
            "partitionBy": "[]"
        },
        "isolationLevel": "Serializable",
        "isBlindAppend": false,
        "operationMetrics": {
            "numFiles": "1",
            "numOutputRows": "5",
            "numOutputBytes": "854"
        },
        "tags": {
            "VORDER": "true"
        },
        "engineInfo": "Apache-Spark/3.4.1.5.3-117503204 Delta-Lake/2.4.0.9",
        "txnId": "********-****-****-****-************"
    }
}
```


# その他
https://powerbi.connpass.com/

https://www.microsoft.com/en-us/power-platform/products/power-bi

https://www.microsoft.com/en-us/microsoft-fabric