查询数据
查询数据是在 Azure Databricks 中执行几乎所有数据驱动任务的基础步骤。 无论使用何种语言或工具,工作负载首先针对表或其他数据源定义查询,然后执行操作以从数据中获取见解。 本文概述了跨各种 Azure Databricks 产品/服务运行查询的核心概念和过程,并包含可根据你的用例进行调整的代码示例。
可以使用以下方法以交互方式查询数据:
- 笔记本
- SQL 编辑器
- 文件编辑器
- 仪表板
还可以在 Delta Live Tables 管道或作业中运行查询。
有关 Azure Databricks 上的流式查询的概述,请参阅查询流式数据。
可以使用 Azure Databricks 查询哪些数据?
Azure Databricks 支持查询多种格式、多种企业系统内的数据。 使用 Azure Databricks 查询的数据属于以下两大类之一:Databricks 湖屋中的数据和外部数据。
Databricks 湖屋中有哪些数据?
默认情况下,Databricks Data Intelligence Platform 会将所有数据存储在 Databricks 湖屋中。
这意味着,当你运行基本 CREATE TABLE
语句来创建新表时,你已创建了一个湖屋表。 湖屋数据具有以下属性:
- 以 Delta Lake 格式存储。
- 存储在云对象存储中。
- 受 Unity Catalog 管理。
Azure Databricks 上的大部分湖屋数据以托管表的形式注册在 Unity Catalog 中。 托管表提供最简单的语法,其行为与大多数关系数据库管理系统中的其他表类似。 对于大多数用例,都建议使用托管表,并且托管表适合所有不想担心数据存储实现细节的用户。
非托管表(或外部表)是在指定了 LOCATION
的情况下注册的表。 “外部”一词可能会产生误导,因为外部 Delta 表仍然是湖屋数据。 直接从其他 Delta 读取器客户端访问表的用户可能会首选非托管表。 有关表语义差异的概述,请参阅 什么是表和视图?。
某些旧式工作负载可能会通过文件路径与 Delta Lake 数据专门交互,并且根本不注册表。 这些数据仍然是湖屋数据,但可能更难发现,因为它未注册到 Unity Catalog。
注意
你的工作区管理员可能尚未升级你的数据治理以使用 Unity Catalog。 即使没有 Unity Catalog,你也仍然可以获得 Databricks 湖屋的许多好处,但在本文或整个 Azure Databricks 文档中列出的所有功能并非均受支持。
哪些数据被视为外部数据?
任何不在 Databricks 湖屋中的数据都可以被视为外部数据。 外部数据的一些示例包括:
- 向 Lakehouse Federation 注册的外来表。
- 受 Parquet 支持的 Hive 元存储中的表。
- 受 JSON 支持的 Unity Catalog 中的外部表。
- 存储在云对象存储中的 CSV 数据。
- 从 Kafka 读取的流式数据。
Azure Databricks 支持配置与许多数据源的连接。 请参阅连接到数据源。
虽然可以针对以多种格式、在多种外部系统中存储的数据使用 Unity Catalog 来管理对这些数据的访问并定义表,但若要使数据可被视为湖屋中的数据,Delta Lake 就是一个必要条件了。
Delta Lake 在 Azure Databricks 中提供所有事务性保证,这对于保持数据完整性和一致性至关重要。 如果要详细了解 Azure Databricks 数据上的事务性保证以及它们为何重要,请参阅 Azure Databricks 上的 ACID 保证是什么?。
大多数 Azure Databricks 用户查询湖屋数据和外部数据的组合。 与外部数据进行连接始终是用于将数据引入到湖屋的数据引入和 ETL 管道的第一步。 若要了解如何引入数据,请参阅将数据引入到 Databricks 湖屋中。
按名称查询表
对于注册为表的所有数据,Databricks 建议使用表名称进行查询。
如果你使用的是 Unity Catalog,表将使用具有以下格式的三层命名空间:<catalog-name>.<schema-name>.<table-name>
。
如果没有 Unity Catalog,表标识符将使用格式 <schema-name>.<table-name>
。
注意
Azure Databricks 从 Apache Spark 继承了其大部分 SQL 语法,它不区分 SCHEMA
和 DATABASE
。
所有 Azure Databricks 执行上下文和受支持的语言都支持按表名称查询。
SQL
SELECT * FROM catalog_name.schema_name.table_name
Python
spark.read.table("catalog_name.schema_name.table_name")
按路径查询数据
可以使用文件路径查询结构化、半结构化和非结构化的数据。 Azure Databricks 上的大多数文件都由云对象存储提供支持。 请参阅使用 Azure Databricks 上的文件。
Databricks 建议使用 Unity Catalog 配置对云对象存储的所有访问权限,并为直接查询的对象存储位置定义卷。 卷使用文件路径的目录和架构名称,为云对象存储中的位置和文件提供人工可读的别名。 请参阅使用 Unity Catalog 连接到云对象存储和服务。
以下示例演示如何使用 Unity Catalog 卷路径读取 JSON 数据:
SQL
SELECT * FROM json.`/Volumes/catalog_name/schema_name/volume_name/path/to/data`
Python
spark.read.format("json").load("/Volumes/catalog_name/schema_name/volume_name/path/to/data")
对于未配置为 Unity Catalog 卷的云位置,可以直接使用 URI 查询数据。 必须配置对云对象存储的访问权限才能使用 URI 查询数据。 请参阅配置对 Azure Databricks 云对象存储的访问权限。
以下示例演示如何使用 URI 查询 Azure Data Lake Storage Gen2、GCS 和 S3 中的 JSON 数据:
SQL
SELECT * FROM json.`abfss://container-name@storage-account-name.dfs.core.windows.net/path/to/data`;
SELECT * FROM json.`gs://bucket_name/path/to/data`;
SELECT * FROM json.`s3://bucket_name/path/to/data`;
Python
spark.read.format("json").load("abfss://container-name@storage-account-name.dfs.core.windows.net/path/to/data")
spark.read.format("json").load("gs://bucket_name/path/to/data")
spark.read.format("json").load("s3://bucket_name/path/to/data")
使用 SQL 仓库查询数据
Azure Databricks 在以下接口中将 SQL 仓库用于计算:
- SQL 编辑器
- Databricks SQL 查询
- 仪表板
- 旧版仪表板
- SQL 警报
可以选择将 SQL 仓库与以下产品配合使用:
- Databricks 笔记本
- Databricks 文件编辑器
- Databricks 作业
通过 SQL 仓库查询数据时,只能使用 SQL 语法。 其他编程语言和 API 不受支持。
对于为 Unity Catalog 启用的工作区,SQL 仓库始终使用 Unity Catalog 来管理对数据源的访问。
在 SQL 仓库上运行的大多数查询将表作为目标。 将数据文件作为目标的查询应利用 Unity Catalog 卷来管理对存储位置的访问。
在 SQL 仓库上运行的查询中直接使用 URI 可能会导致意外错误。
使用通用计算或作业计算查询数据
从 Databricks 笔记本、工作流和文件编辑器运行的大多数查询均针对配置了 Databricks Runtime 的计算群集运行。 可以将这些群集配置为以交互方式运行,或将其部署为用于为工作流提供支持的作业计算。 Databricks 建议始终对非交互式工作负载使用作业计算。
交互式工作负载与非交互式工作负载
许多用户发现,在开发过程中处理转换时查看查询结果很有帮助。 将交互式工作负载从通用计算转移到作业计算,可以通过删除显示结果的查询来节省时间和处理成本。
Apache Spark 使用惰性代码执行,这意味着仅在必要时计算结果,并且在你不强制显示结果的情况下可以将针对数据源的多个转换或查询优化为单个查询。 这与 pandas 中使用的预先执行模式形成鲜明对比,后者要求在将结果传递给下一个方法之前按顺序处理计算。
如果你的目标是将清理、转换、聚合的数据保存为新数据集,则应在安排代码运行之前从代码中删除显示结果的查询。
对于小型操作和小型数据集,时间和成本节省可能微乎其微。 然而,在进行大型操作时,可能会浪费大量时间来计算结果并将结果输出到笔记本,而这些结果可能不会被人工检查。 存储这些结果后,可能会从保存的输出中查询它们,但成本几乎为零。