diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml index a197d8d..7be6d1a 100644 --- a/.github/workflows/packaging.yml +++ b/.github/workflows/packaging.yml @@ -48,7 +48,7 @@ jobs: - name: Build documentation # Using mkdocs build is the standard way to generate the site - run: mkdocs build --strict + run: mkdocs build - name: Compress docs for artifact upload run: | diff --git a/docs/contributors-guide.zh.md b/docs/contributors-guide.zh.md new file mode 100644 index 0000000..38eb734 --- /dev/null +++ b/docs/contributors-guide.zh.md @@ -0,0 +1,179 @@ +--- +title: 贡献者指南 +--- + + + +# 贡献者指南 + +本指南将详细介绍作为 SpatialBench 贡献者,应如何搭建开发环境。 + +## Fork 并克隆仓库 + +第一步是创建仓库的个人副本,并将其与主项目关联起来。 + +1. Fork 仓库 + + * 访问官方 [SpatialBench GitHub 仓库](https://github.com/apache/sedona-spatialbench)。 + * 点击右上角的 **Fork** 按钮,这会在你的 GitHub 账号下创建一份完整的项目副本。 + +2. 克隆你的 fork + + * 接下来,将你刚刚 fork 的仓库克隆到本地。该命令会将仓库下载到名为 `sedona-spatialbench` 的新目录中。 + * 请将 `YourUsername` 替换为你实际的 GitHub 用户名。 + + ```shell + git clone https://github.com/YourUsername/sedona-spatialbench.git + cd sedona-spatialbench + ``` + +3. 配置 remote + + * 你的本地仓库需要知道原始项目的位置,以便后续拉取更新。我们通常会添加一个名为 upstream 的远程地址,指向 SpatialBench 主仓库。 + * 你的 fork 会被自动配置为 origin 远程。 + + ```shell + # 将主仓库添加为名为 "upstream" 的远程 + git remote add upstream https://github.com/apache/sedona-spatialbench.git + ``` + +4. 验证配置 + + * 运行以下命令,确认你正确地配置了两个远程:origin(你的 fork)和 upstream(主仓库)。 + + ```shell + git remote -v + ``` + + * 输出应当类似于: + + ```shell + origin https://github.com/YourUsername/sedona-spatialbench.git (fetch) + origin https://github.com/YourUsername/sedona-spatialbench.git (push) + upstream https://github.com/apache/sedona-spatialbench.git (fetch) + upstream https://github.com/apache/sedona-spatialbench.git (push) + ``` + +## 开发环境搭建 + +SpatialBench 使用 Rust 编写,并采用标准的 cargo workspace。你可以从 rustup.rs 安装一个较新的 Rust 编译器和 cargo。 + +运行测试: + +```shell +cargo test +``` + +可以使用以下命令运行 CLI 的本地开发版本: + +```shell +cargo run --bin spatialbench-cli +``` + +## 调试 + +### IDE + +调试 Rust 代码最方便的方式是编写或定位一个能够触发目标行为的测试,然后在 IDE 中通过 [rust-analyzer](https://www.jetbrains.com/help/fleet/using-rust-analyzer.html) 扩展使用 Debug 模式运行该测试。 + +### CLI 的详细输出 + +调试 SpatialBench CLI 时,可以启用详细输出,以查看更详细的日志: + +启用详细输出(info 级别日志): + +```shell +cargo run --bin spatialbench-cli -- --scale-factor 1 --verbose +``` + +或者通过环境变量进行更精细的控制: + +```shell +RUST_LOG=debug cargo run --bin spatialbench-cli -- --scale-factor 1 +``` + +`--verbose` 标志会将日志级别设置为 info,并忽略 RUST_LOG 环境变量。如果未指定 `--verbose`,则日志通过 `RUST_LOG` 进行配置。 + +### 日志级别 + +你可以使用 `RUST_LOG` 控制日志的粒度: + +```shell +# 仅显示错误 +RUST_LOG=error cargo run --bin spatialbench-cli -- --scale-factor 1 + +# 显示警告和错误 +RUST_LOG=warn cargo run --bin spatialbench-cli -- --scale-factor 1 + +# 显示 info、警告和错误 +RUST_LOG=info cargo run --bin spatialbench-cli -- --scale-factor 1 + +# 显示调试输出 +RUST_LOG=debug cargo run --bin spatialbench-cli -- --scale-factor 1 + +# 显示 trace 输出(非常详细) +RUST_LOG=trace cargo run --bin spatialbench-cli -- --scale-factor 1 + +# 仅显示特定模块的调试输出 +RUST_LOG=spatialbench=debug cargo run --bin spatialbench-cli -- --scale-factor 1 +``` + +## 测试 + +我们使用 cargo 来运行 Rust 测试: + +```shell +cargo test +``` + +也可以仅对某个 crate 运行测试: + +```shell +cd spatialbench +cargo test +``` + +## 代码风格检查 + +安装 pre-commit。它会自动运行通过 CI 所必需的各项检查(例如代码格式化): + +```shell +pre-commit install +``` + +此外,在推送新的 Rust 改动前,你还应当运行 clippy 来发现常见的代码问题。该检查不包含在 pre-commit 中,因此需要手动运行。修复它给出的所有建议后,再运行一次以确认没有其他需要修改的地方: + +```shell +cargo clippy +``` + +## 文档 + +为 SpatialBench 文档做贡献的步骤如下: + +1. 克隆仓库并创建一个 fork。 +2. 安装文档相关依赖: + ```shell + pip install -r docs/requirements.txt + ``` +3. 修改文档文件。 +4. 使用以下命令在本地预览改动: + * `mkdocs serve` —— 启动支持实时刷新的文档服务器。 + * `mkdocs build` —— 构建文档站点。 + * `mkdocs -h` —— 打印帮助信息并退出。 +5. 推送改动并提交 Pull Request。 diff --git a/docs/datasets-generators.zh.md b/docs/datasets-generators.zh.md new file mode 100644 index 0000000..88be254 --- /dev/null +++ b/docs/datasets-generators.zh.md @@ -0,0 +1,140 @@ +--- +title: SpatialBench 数据集与生成器 +--- + + + +# SpatialBench 数据集与生成器 + +本页面介绍 SpatialBench 数据集,并演示如何使用生成器来生成相应的空间数据表。 + +SpatialBench 是一个面向地理空间的基准测试套件,用于评估和优化数据系统中的空间查询性能。它借鉴了星型模式基准测试(SSB)和纽约市出租车与豪华轿车委员会(NYC TLC)数据集的设计思想,将真实的城市出行场景与标准化的基准测试方法相结合。 + +SpatialBench 采用了 SSB 中常见的星型模式结构,并在此基础上增加了空间属性,如上车点和下车点、区域的空间多边形边界以及建筑物轮廓。这些空间扩展使 SpatialBench 能够有效测试包括空间连接、基于距离的查询、空间聚合、以及点在多边形内分析在内的地理空间操作。 + +通过结合 SSB 的系统性方法与源自 NYC TLC 数据的真实场景,SpatialBench 提供了与城市出行和空间分析工作负载高度相关的、具有实际意义的基准测试。 + +## 数据模型 + +SpatialBench 包含以下表: + +* **Trip(事实表)**:记录每一次行程,包含空间属性(上车点和下车点)、行程费用、距离、时长,以及上车时间和下车时间。 +* **Customer**:表示预订行程的客户。 +* **Driver**:表示完成行程的司机。 +* **Vehicle**:行程使用车辆的详细信息。 +* **Zone**:表示城市区域或行政分区的多边形边界。 +* **Building**:表示建筑物位置、类型和名称的多边形轮廓。 + +| **表名** | **类型** | **缩写前缀** | **主要作用** | **空间属性** | **每个规模因子(SF)下的大小** | +|-----------|----------|-----------|------------------|------------------------|--------------------------------| +| Building | 维度表 | b_ | 表示建筑物位置的多边形轮廓 | 多边形轮廓 | 20K × (1 + log₂(SF)) | +| Customer | 维度表 | c_ | 表示客户 | 无 | 30K × SF | +| Driver | 维度表 | s_ | 表示司机 | 无 | 500 × SF | +| Trip | 事实表 | t_ | 记录每次行程 | 上车点 / 下车点(坐标) | 6M × SF | +| Vehicle | 维度表 | v_ | 车辆详情 | 无 | 100 × SF | +| Zone | 维度表 | z_ | 城市区域的多边形边界 | 多边形边界 | 按 SF 范围分级(详见下表) | + +### Zone 表的扩展规则 + +| **规模因子(SF)** | **包含的 Zone 子类型** | **Zone 数量** | +|----------------------|----------------------------|---------------------| +| [0, 10) | microhood、macrohood、county | 156,095 | +| [10, 100) | + neighborhood | 455,711 | +| [100, 1000) | + localadmin、locality、region、dependency | 1,035,371 | +| [1000+) | + country | 1,035,749 | + +![schema](image/datasets-schema.png) + +### **地理覆盖范围** + +SpatialBench 的数据生成器使用按大洲划分的仿射变换。每个大洲都有一个边界多边形定义,确保生成的数据大多落在陆地上,并自然引入真实地理分布所固有的偏斜。 + +边界多边形如下: + +| 区域 | 边界多边形 | +|--------|------------------| +| 非洲 | `POLYGON ((-20.062752 -40.044425, 64.131567 -40.044425, 64.131567 37.579421, -20.062752 37.579421, -20.062752 -40.044425))` | +| 欧洲 | `POLYGON ((-11.964479 37.926872, 64.144374 37.926872, 64.144374 71.82884, -11.964479 71.82884, -11.964479 37.926872))` | +| 南亚 | `POLYGON ((64.58354 -9.709049, 145.526096 -9.709049, 145.526096 51.672557, 64.58354 51.672557, 64.58354 -9.709049))` | +| 北亚 | `POLYGON ((64.495655 51.944267, 178.834704 51.944267, 178.834704 77.897255, 64.495655 77.897255, 64.495655 51.944267))` | +| 大洋洲 | `POLYGON ((112.481901 -48.980212, 180.768942 -48.980212, 180.768942 -10.228433, 112.481901 -10.228433, 112.481901 -48.980212))` | +| 南美洲 | `POLYGON ((-83.833822 -56.170016, -33.904338 -56.170016, -33.904338 12.211188, -83.833822 12.211188, -83.833822 -56.170016))` | +| 北美洲南部 | `POLYGON ((-124.890724 12.382931, -69.511192 12.382931, -69.511192 42.55308, -124.890724 42.55308, -124.890724 12.382931))` | +| 北美洲北部 | `POLYGON ((-166.478008 42.681087, -52.053245 42.681087, -52.053245 72.659041, -166.478008 72.659041, -166.478008 42.681087))` | + +![continents](image/datasets-continents.png) + +### 分布选项 + +默认情况下,SpatialBench 在生成 trip 表和 building 表时,会使用按大洲划分的仿射变换,并配合层次化 Thomas 分布(Hierarchical Thomas)生成点。 + +为了让数据更贴近真实情况,你可以在生成表时从多种空间分布中进行选择: + +* Uniform(均匀分布):在单位正方形内均匀分布点。 +* Normal(正态分布):围绕均值的高斯分布,方差可配置。 +* Diagonal(对角线分布):点集中分布在 y=x 对角线附近,可配置缓冲区。 +* Bit(比特分布):由概率和位数控制的递归类网格图案。 +* Sierpinski(谢尔宾斯基分布):自相似分形图案,覆盖呈高度偏斜。 +* Thomas:带有真实热点和长尾偏斜的聚类分布。 +* Hierarchical Thomas(层次化 Thomas):多级聚类(城市 → 街区 → 点),适合模拟城市人口聚集的模式。 + +这些选项可以让你根据自己的基准测试需求来调整空间偏斜度。 + +要详细了解 SpatialBench 支持的空间分布、控制这些分布的参数以及它们对数据的影响,请参见 [SpatialBench 数据分布](spatialbench-distributions.md) 页面。 + + +## 数据生成器 + +可以使用以下命令为规模因子 1(SF1)生成所有表: + +``` +spatialbench-cli -s 1 --format=parquet --output-dir sf1-parquet +``` + +你也可以通过提供 S3 URI 将数据直接生成到 Amazon S3: + +``` +spatialbench-cli -s 1 --format=parquet --output-dir s3://my-bucket/sf1-parquet +``` + +关于 AWS 凭据的配置,请参见[快速开始](quickstart.md#s3)。 + +`sf1-parquet` 目录内会包含以下文件: + +* `building.parquet` +* `customer.parquet` +* `driver.parquet` +* `trip.parquet` +* `vehicle.parquet` +* `zone.parquet` + +SpatialBench 数据生成器的完整使用说明,请参见 [README](https://github.com/apache/sedona-spatialbench)。 + +## 数据大小 + +下表给出了在不同规模因子下,各表未压缩的 Parquet 文件大小: + +| 类别 | SF1 | SF10 | SF100 | SF1000 | +|----------|------------|------------|------------|-------------| +| Zone | 1.3 GB | 2.0 GB | 5.4 GB | 5.7 GB | +| Trip | 471.1 MB| 5.0 GB | 50.4 GB | 512.7 GB | +| Building | 2.4 MB | 10.2 MB | 18.0 MB | 0.03 GB | +| Customer | 2.5 MB | 23.1 MB | 227.1 MB| 2.2 GB | +| Driver | 0.04 MB | 0.4 MB | 4.0 MB | 0.03 GB | +| Vehicle | 0.01 MB | 0.03 MB | 0.3 MB | 0.003 GB | +| **合计** | **1.8 GB** | **7.0 GB** | **56.0 GB** | **520.6 GB** | diff --git a/docs/index.zh.md b/docs/index.zh.md new file mode 100644 index 0000000..aebd1ee --- /dev/null +++ b/docs/index.zh.md @@ -0,0 +1,102 @@ +--- +title: SpatialBench +--- + + + +SpatialBench 是一个用于评估各类数据库系统中地理空间 SQL 分析查询性能的基准测试套件,能够让你在任意查询引擎上轻松地基于真实场景的数据集运行测试。 + +该方法论保持中立公正,你可以在任意环境中运行基准测试,以比较不同运行时之间的相对性能。 + +## 为什么选择 SpatialBench + +SpatialBench 的诞生,源于现有标准数据库基准测试无法充分覆盖地理空间查询的独特需求。SpatialBench 提供了一个开源、标准化、可扩展的框架,专门为地理空间分析而设计。 + +SpatialBench 借鉴了星型模式基准测试(Star Schema Benchmark,SSB)和纽约市出租车数据的思路,将真实的城市出行场景与扩展了空间属性的星型模式(如上车/下车点、区域以及建筑物轮廓等)相结合。 + +这种设计能够评估以下空间操作: + +* 空间连接(Spatial joins) +* 距离查询(Distance queries) +* 聚合(Aggregations) +* 点在多边形内分析(Point-in-polygon analysis) + +下面让我们深入了解 SpatialBench 的优势。 + +## 主要特性 + +为了确保测试的公平性和全面性,SpatialBench 提供了以下优势: + +* 提供包含原生几何列的真实空间数据集。 +* 包含一套查询,可测试空间谓词、空间连接等多种操作。 +* 内置合成数据生成器,用于生成一致的测试数据。 +* 提供可配置的规模因子(Scale Factor),便于在从单机到大规模云集群的各种环境中进行性能测试。 +* 在所有环境中均能给出一致且可复现的基准测试结果。 +* 采用完整记录、立场中立的方法论,便于公平比较。 +* 开源且由社区驱动,倡导透明性和持续改进。 + +## 生成合成数据 + +下面是安装合成数据生成器的方法: + +``` +cargo install --path ./spatialbench-cli +``` + +下面是生成合成数据集的方法: + +``` +spatialbench-cli -s 1 --format=parquet +``` + +完整的数据生成说明请参见项目仓库的 [README](https://github.com/apache/sedona-spatialbench)。 + +## 示例查询 + +下面是一个示例查询,统计每栋建筑物 500 米范围内的行程数量: + +```sql +SELECT + b.b_buildingkey, + b.b_name, + COUNT(*) AS nearby_pickup_count +FROM trip t +JOIN building b +ON ST_DWithin(t.t_pickup_loc, b.b_boundary, 500) +GROUP BY b.b_buildingkey, b.b_name +ORDER BY nearby_pickup_count DESC; +``` + +该查询先执行一个基于距离的连接,再进行聚合。它非常适合用于评测可处理矢量几何的空间引擎的性能。 + +## 自动化测试 + +SpatialBench 包含一个在 GitHub Actions 上运行的自动化基准测试,用于验证所有查询能够在受支持的引擎(DuckDB、GeoPandas、SedonaDB 和 Spatial Polars)上完整运行。 + +**[查看最新的测试结果 →](https://github.com/apache/sedona-spatialbench/actions/workflows/benchmark.yml)** + +点击任一成功的工作流运行记录,并向下滚动到 **Summary** 部分即可查看结果。 + +!!! note + GitHub Actions 上的基准测试主要用于验证查询的正确性和可运行性,并不适用于严肃的性能对比。如需进行有意义的性能基准测试,请参阅 [单节点基准测试](single-node-benchmarks.md) 页面。 + +## 加入社区 + +欢迎在 [GitHub Discussions](https://github.com/apache/sedona/discussions) 发起讨论,或加入 [Discord 社区](https://discord.gg/9A3k5dEBsY),向开发者提出任何问题。 + +我们期待与你一同推进这些基准测试的工作! diff --git a/docs/overview-methodology.zh.md b/docs/overview-methodology.zh.md new file mode 100644 index 0000000..c83721e --- /dev/null +++ b/docs/overview-methodology.zh.md @@ -0,0 +1,93 @@ +--- +title: SpatialBench 方法论 +--- + + + +SpatialBench 是一套具有代表性的空间查询开放基准测试套件,旨在评估不同引擎在多种规模因子下的性能。 + +SpatialBench 查询是比较不同引擎在分析型空间工作负载下相对性能的有效手段。你可以使用较小的规模因子进行单机查询,也可以使用较大的规模因子来评测在云端分布式计算的引擎。 + +下面我们更深入地探讨 SpatialBench 为什么如此重要。 + +## 为什么需要 SpatialBench? + +空间工作流通常包含空间连接、空间过滤、以及 KNN 连接等空间专用操作。 + +通用的分析查询基准测试无法覆盖空间查询。它们关注的是表格数据上的分析查询,如连接和聚合。下面是一些常见的分析型基准测试: + +* [TPC-H](https://www.tpc.org/tpch/) +* [TPC-DS](https://www.tpc.org/tpcds/) +* [ClickBench](https://benchmark.clickhouse.com/) +* [YCSB](https://github.com/brianfrankcooper/YCSB) +* [db-benchmark](https://duckdblabs.github.io/db-benchmark/) + +这些分析型基准测试有助于评估分析查询性能,但其结果并不一定能反映空间查询的性能。一个引擎在大型表格聚合上可能表现出色,但在空间连接上却可能非常糟糕。 + +SpatialBench 专为空间查询而设计,是评估引擎空间性能的最佳现代方案。下面给出一些使用建议,帮助你获得最准确、最公平的结果。 + +## 硬件和软件 + +SpatialBench 基准测试在通用硬件上运行,每次发布都会完整披露所使用的软件版本。 + +在对比不同运行时时,开发者应当尽可能使用相近的硬件和软件版本。如果一个运行时的计算能力远低于另一个,这种对比是没有意义的。 + +SpatialBench 基准测试结果应始终连同对应的硬件/软件规格一起呈现,以便读者评估比较的可靠性。 + +## 准确对比不同的引擎 + +要对本质上不同的引擎(如 PostGIS(OLTP 数据库)、DuckDB(OLAP 数据库)以及 GeoPandas(Python 引擎))进行公平比较是颇具挑战的。 + +例如,让我们看看两个引擎执行同一查询的方式有何不同: + +* PostGIS:创建表、将数据加载到表中、构建索引(可能较为耗时)、执行查询 +* GeoPandas:将数据读取至内存并执行查询 + +由于 PostGIS 和 GeoPandas 在执行查询的方式上存在差异,因此在呈现查询运行时间时需要格外谨慎。例如,你不能忽略 PostGIS 构建索引所花费的时间,因为它可能是查询中最耗时的部分。对于运行临时查询的用户来说,这是非常关键的细节。 + +SpatialBench 在呈现结果时,会尽量给出查询各相关阶段的运行时间,以帮助用户更好地解读结果。 + +## 基准测试中的引擎调优 + +引擎可以通过配置参数或优化代码来进行调优。例如,你可以通过调优 JVM 来优化 Spark 代码,也可以通过添加索引来优化 GeoPandas 代码。如果一个基准测试仅对某一个引擎进行了调优,却没有对其他引擎做同样的调优,那么这样的结果是不可靠的。 + +SpatialBench 完整披露所有性能调优信息。部分结果会同时呈现“开箱即用”和“充分调优”两种情形,以便更全面地反映默认性能以及专家用户所能达到的性能。 + +## 开源基准测试与厂商基准测试 + +SpatialBench 基准测试报告了部分开源空间引擎/数据库的结果。 + +SpatialBench 仓库本身不会报告任何专有引擎或厂商运行时的结果。厂商可以自由地使用 SpatialBench 的数据生成器并自行运行基准测试。我们希望厂商在使用本基准测试时能注明出处,并完整披露结果,以便其他从业者能够复现这些结果。 + +## 如何贡献 + +为 SpatialBench 项目做贡献的方式多种多样: + +* 提交 [Pull Request](https://github.com/apache/sedona-spatialbench/pulls) 来添加新特性 +* 创建 [Issue](https://github.com/apache/sedona-spatialbench/issues) 来报告 bug +* 复现结果,或协助接入新的空间引擎 +* 发布厂商基准测试 + +下面是与团队沟通的渠道: + +* 在 [Apache Sedona Discord](https://discord.gg/9A3k5dEBsY) 上交流 +* 创建 [GitHub Discussions](https://github.com/apache/sedona/discussions) + +## 未来工作 + +在下一个发布版本中,我们会加入栅格数据集和栅格查询。它们将对引擎处理栅格数据的能力进行压力测试,同时也会展示在矢量数据与栅格数据连接场景下的性能表现。 diff --git a/docs/queries.zh.md b/docs/queries.zh.md new file mode 100644 index 0000000..9ba5e05 --- /dev/null +++ b/docs/queries.zh.md @@ -0,0 +1,611 @@ +# 运行 SpatialBench 查询 + +本笔记本包含构成 SpatialBench 基准测试的所有查询。 + +SpatialBench 是一个用于评估各类数据库系统中地理空间 SQL 分析查询性能的基准测试。这些查询代表了常见的真实世界地理空间分析任务,旨在测试各种空间函数和连接条件。 + +该基准测试使用了一个真实但合成的、以交通运输为主题的数据集,以确保查询能够反映实际的使用场景。通过运行这些查询,你可以在一致且中立的基础上评估并比较不同空间查询引擎的相对性能。 + +## 在开始之前 + +在运行此笔记本前,请确保已安装 `requirements.txt` 中列出的依赖: + + +```python +%pip install -r ~/sedona-spatialbench/docs/requirements.txt +``` + + ... + ... + Note: you may need to restart the kernel to use updated packages. + + +此外,请安装 SpatialBench CLI 并在本机生成合成数据: + +``` +# SpatialBench CLI +cargo install --path ./spatialbench-cli +# 将基准测试数据生成到 sf1-parquet 目录 +spatialbench-cli -s 1 --format=parquet --output-dir sf1-parquet +``` + + +```python +import sedona.db +``` + + +```python +sd = sedona.db.connect() +``` + + +```python +sd.read_parquet(f"../sf1-parquet/building.parquet").to_view("building") +sd.read_parquet(f"../sf1-parquet/customer.parquet").to_view("customer") +sd.read_parquet(f"../sf1-parquet/driver.parquet").to_view("driver") +sd.read_parquet(f"../sf1-parquet/trip.parquet").to_view("trip") +sd.read_parquet(f"../sf1-parquet/vehicle.parquet").to_view("vehicle") +sd.read_parquet(f"../sf1-parquet/zone.parquet").to_view("zone") +``` + +## Q1:在距离 Sedona 市中心 50 公里以内的行程,按距离排序 + +**真实场景:** 根据与市中心的距离对行程进行识别和排序,用于城市规划和交通分析。 + +该查询找出所有从亚利桑那州 Sedona 市中心 50 公里范围内出发的出租车或网约车行程。对于每一个符合条件的行程,结果会显示行程 ID、上车经纬度、上车时间,并计算上车点到 Sedona 市中心的精确距离。结果按距离升序排序,最靠近市中心的行程排在最前面,便于查看哪些行程最贴近市中心。 + +**被测试的空间查询特性:** + +1. 基于距离的空间过滤(ST_DWithin) +2. 到固定点的距离计算 +3. 坐标提取(ST_X、ST_Y) +4. 按空间距离排序 + + +```python +sd.sql(""" +SELECT + t.t_tripkey, + ST_X(ST_GeomFromWKB(t.t_pickuploc)) AS pickup_lon, + ST_Y(ST_GeomFromWKB(t.t_pickuploc)) AS pickup_lat, + t.t_pickuptime, + ST_Distance( + ST_GeomFromWKB(t.t_pickuploc), + ST_GeomFromText('POINT (-111.7610 34.8697)') + ) AS distance_to_center +FROM trip t +WHERE ST_DWithin( + ST_GeomFromWKB(t.t_pickuploc), + ST_GeomFromText('POINT (-111.7610 34.8697)'), + 0.45 -- Sedona 中心 50km 半径,以度为单位 +) +ORDER BY distance_to_center ASC, t.t_tripkey ASC +""").show(3) +``` + + ┌───────────┬────────────────┬──────────────┬─────────────────────┬──────────────────────┐ + │ t_tripkey ┆ pickup_lon ┆ pickup_lat ┆ t_pickuptime ┆ distance_to_center │ + │ int64 ┆ float64 ┆ float64 ┆ timestamp ┆ float64 │ + ╞═══════════╪════════════════╪══════════════╪═════════════════════╪══════════════════════╡ + │ 1451371 ┆ -111.791052127 ┆ 34.826733457 ┆ 1998-08-12T06:47:01 ┆ 0.05243333056935387 │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 2047835 ┆ -111.706967009 ┆ 34.883889472 ┆ 1992-04-08T07:36:09 ┆ 0.055865062714050374 │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 3936870 ┆ -111.827619221 ┆ 34.882950924 ┆ 1998-11-10T13:32:07 ┆ 0.06792427838042854 │ + └───────────┴────────────────┴──────────────┴─────────────────────┴──────────────────────┘ + + +## Q2:统计 Coconino 县(Arizona)区域内起始的行程数量 + +**真实场景:** 统计某个特定行政边界(县)内起始的所有行程数量,用于区域交通统计。 + +该查询统计有多少出租车或网约车行程在亚利桑那州 Coconino 县内出发。其做法是判断每个行程的上车点是否落在该县的地理边界内。结果是一个简单的总数,表示在 Coconino 县范围内出发的行程总数。 + +**被测试的空间查询特性:** + +1. 点在多边形内的空间过滤(ST_Intersects) +2. 包含空间几何选择的子查询 +3. 对经空间过滤的数据进行简单聚合 + + +```python +sd.sql(""" +SELECT COUNT(*) AS trip_count_in_coconino_county +FROM trip t +WHERE ST_Intersects( + ST_GeomFromWKB(t.t_pickuploc), + ( + SELECT ST_GeomFromWKB(z.z_boundary) + FROM zone z + WHERE z.z_name = 'Coconino County' + LIMIT 1 + ) +) +""").show(3) +``` + + ┌───────────────────────────────┐ + │ trip_count_in_coconino_county │ + │ int64 │ + ╞═══════════════════════════════╡ + │ 541 │ + └───────────────────────────────┘ + + +## Q3:Sedona 市中心 15 公里半径内的月度行程统计 + +**真实场景:** 跟踪都市区的月度出行趋势和性能指标,并进行季节性分析。 + +该查询通过将行程按月度汇总,分析 Sedona 周边的出租车和网约车行程模式。它会查看所有在 Sedona 周边 15 公里范围内(即 10km 的边界框加上 5km 的缓冲区)起始的行程,并为每个月份计算关键统计量,包括总行程数、平均行驶距离、平均行程时长以及平均车费。结果按月份按时间顺序排列,让你可以观察到 Sedona 地区出行模式的季节性变化趋势。 + +**被测试的空间查询特性:** + +1. 带缓冲区的基于距离空间过滤(ST_DWithin) +2. 时间维度的分组(月度聚合) +3. 在空间过滤后的数据上进行多种统计聚合 + + +```python +sd.sql(""" +SELECT + DATE_TRUNC('month', t.t_pickuptime) AS pickup_month, + COUNT(t.t_tripkey) AS total_trips, + AVG(t.t_distance) AS avg_distance, + AVG(t.t_dropofftime - t.t_pickuptime) AS avg_duration, + AVG(t.t_fare) AS avg_fare +FROM trip t +WHERE ST_DWithin( + ST_GeomFromWKB(t.t_pickuploc), + ST_GeomFromText('POLYGON(( + -111.9060 34.7347, -111.6160 34.7347, + -111.6160 35.0047, -111.9060 35.0047, + -111.9060 34.7347 + ))'), -- Sedona 周边的边界框 + 0.045 -- 额外 5km 缓冲(以度计) +) +GROUP BY pickup_month +ORDER BY pickup_month +""").show(3) +``` + + ┌─────────────────────┬─────────────┬──────────────┬─────────────────────────────────┬─────────────┐ + │ pickup_month ┆ total_trips ┆ avg_distance ┆ avg_duration ┆ avg_fare │ + │ timestamp ┆ int64 ┆ decimal128 ┆ duration ┆ decimal128 │ + ╞═════════════════════╪═════════════╪══════════════╪═════════════════════════════════╪═════════════╡ + │ 1992-04-01T00:00:00 ┆ 2 ┆ 0.000020000 ┆ 0 days 1 hours 23 mins 47.000 … ┆ 0.000075000 │ + ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 1992-07-01T00:00:00 ┆ 1 ┆ 0.000010000 ┆ 0 days 0 hours 58 mins 58.000 … ┆ 0.000040000 │ + ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 1994-02-01T00:00:00 ┆ 2 ┆ 0.000020000 ┆ 0 days 1 hours 23 mins 50.000 … ┆ 0.000050000 │ + └─────────────────────┴─────────────┴──────────────┴─────────────────────────────────┴─────────────┘ + + +## Q4:按小费金额排序的前 1000 个行程在各区域的分布 + +**真实场景:** 分析高价值行程(按小费金额)的地理分布,从而了解高端服务区域。 + +该查询分析前 1000 个小费最高的行程,识别出哪些街区或区域产生了最多的“慷慨小费客”。它先找出小费金额最高的 1000 个行程,再判断这些上车点落在哪些地理区域或街区内,并统计每个区域中此类“高小费”行程的数量。结果按高额小费数量进行排名,便于识别出对司机最具吸引力的高小费上车区域。 + +**被测试的空间查询特性:** + +1. 包含排序和限制的子查询 +2. 点在多边形内的空间连接(ST_Within) +3. 在空间连接结果上进行聚合 +4. 包含空间过滤和分组的多步查询 + + +```python +sd.sql(""" +SELECT + z.z_zonekey, + z.z_name, + COUNT(*) AS trip_count +FROM + zone z + JOIN ( + SELECT t.t_pickuploc + FROM trip t + ORDER BY t.t_tip DESC, t.t_tripkey ASC + LIMIT 1000 + ) top_trips + ON ST_Within( + ST_GeomFromWKB(top_trips.t_pickuploc), + ST_GeomFromWKB(z.z_boundary) + ) +GROUP BY z.z_zonekey, z.z_name +ORDER BY trip_count DESC, z.z_zonekey ASC +""").show(3) +``` + + ┌───────────┬─────────────────────────────────┬────────────┐ + │ z_zonekey ┆ z_name ┆ trip_count │ + │ int64 ┆ utf8 ┆ int64 │ + ╞═══════════╪═════════════════════════════════╪════════════╡ + │ 65008 ┆ Ndélé ┆ 35 │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 147530 ┆ 乐山市 ┆ 27 │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 150276 ┆ 锡林郭勒盟 ᠰᠢᠯᠢ ᠶᠢᠨ ᠭᠣᠣᠯ ᠠᠶᠢᠮᠠᠭ ┆ 19 │ + └───────────┴─────────────────────────────────┴────────────┘ + + +## Q5:重复客户的月度出行模式(基于下车点的凸包) + +**真实场景:** 分析常客出行模式的地理分布范围,以了解他们的出行行为。 + +该查询通过测量常客每月行程所覆盖的地理范围,分析他们的月度出行模式。对于每个在某个月内乘坐超过 5 次行程的客户,它会计算其“出行凸包”的面积——即连接当月所有下车点形成的区域的面积。结果可以揭示出哪些客户的出行覆盖范围最广,帮助识别覆盖大面积区域的“重度用户”以及那些只在较小的本地区域内活动的用户。 + +**被测试的空间查询特性:** + +1. 空间聚合(ST_Collect / ARRAY_AGG) +2. 凸包计算(ST_ConvexHull) +3. 复杂几何上的面积计算 +4. 结合时间和客户维度的分组与空间运算 + + +```python +sd.sql(""" +SELECT + c.c_custkey, + c.c_name AS customer_name, + DATE_TRUNC('month', t.t_pickuptime) AS pickup_month, + ST_Area( + ST_ConvexHull(ST_Collect(ST_GeomFromWKB(t.t_dropoffloc))) + ) AS monthly_travel_hull_area, + COUNT(*) as dropoff_count +FROM trip t +JOIN customer c + ON t.t_custkey = c.c_custkey +GROUP BY c.c_custkey, c.c_name, pickup_month +HAVING dropoff_count > 5 -- 仅保留重复客户 +ORDER BY monthly_travel_hull_area DESC, c.c_custkey ASC +""").show(3) +``` + + ┌───────────┬────────────────────┬─────────────────────┬────────────────────┬───────────────┐ + │ c_custkey ┆ customer_name ┆ pickup_month ┆ monthly_travel_hul ┆ dropoff_count │ + │ int64 ┆ utf8 ┆ timestamp ┆ l_area… ┆ int64 │ + ╞═══════════╪════════════════════╪═════════════════════╪════════════════════╪═══════════════╡ + │ 25975 ┆ Customer#000025975 ┆ 1992-02-01T00:00:00 ┆ 34941.303419053635 ┆ 10 │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 12061 ┆ Customer#000012061 ┆ 1997-03-01T00:00:00 ┆ 34607.53871953154 ┆ 14 │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 21418 ┆ Customer#000021418 ┆ 1993-08-01T00:00:00 ┆ 34465.32323910264 ┆ 9 │ + └───────────┴────────────────────┴─────────────────────┴────────────────────┴───────────────┘ + + +## Q6:Sedona 市中心 50 公里半径内各区域的行程统计 + +**真实场景:** 分析特定城市中心周边都市区内各区域的行程模式。 + +该查询分析以亚利桑那州 Sedona 为中心、半径 50 公里范围内所有街区和区域的乘车活动。它通过统计每个区域内起始的行程总数,识别出上车活动最频繁的区域;同时,还计算每个区域内行程的平均费用和平均时长。结果按上车次数排序,揭示出大 Sedona 区域内哪些街区或区域产生的乘车需求最旺盛及其典型的行程特征。 + +**被测试的空间查询特性:** + +1. 带边界框的多边形包含检查(ST_Contains) +2. 点在多边形内的空间连接(ST_Within) + + +```python +sd.sql(""" +SELECT + z.z_zonekey, + z.z_name, + COUNT(t.t_tripkey) AS total_pickups, + AVG(t.t_distance) AS avg_distance, -- Corrected from t_totalamount + AVG(t.t_dropofftime - t.t_pickuptime) AS avg_duration +FROM trip t, zone z +WHERE ST_Intersects( + ST_GeomFromText('POLYGON(( + -112.2110 34.4197, -111.3110 34.4197, + -111.3110 35.3197, -112.2110 35.3197, + -112.2110 34.4197 + ))'), -- Sedona 周边的边界框 + ST_GeomFromWKB(z.z_boundary) + ) + AND ST_Within( + ST_GeomFromWKB(t.t_pickuploc), + ST_GeomFromWKB(z.z_boundary) + ) +GROUP BY z.z_zonekey, z.z_name +ORDER BY total_pickups DESC, z.z_zonekey ASC +""").show(3) +``` + + ┌───────────┬─────────────────┬───────────────┬──────────────┬────────────────────────────────────┐ + │ z_zonekey ┆ z_name ┆ total_pickups ┆ avg_distance ┆ avg_duration │ + │ int64 ┆ utf8 ┆ int64 ┆ decimal128 ┆ duration │ + ╞═══════════╪═════════════════╪═══════════════╪══════════════╪════════════════════════════════════╡ + │ 30084 ┆ Coconino County ┆ 541 ┆ 0.000030406 ┆ 0 days 1 hours 45 mins 16.591 secs │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 30083 ┆ Yavapai County ┆ 292 ┆ 0.000027157 ┆ 0 days 1 hours 36 mins 43.647 secs │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 29488 ┆ Gila County ┆ 39 ┆ 0.000021282 ┆ 0 days 1 hours 16 mins 59.769 secs │ + └───────────┴─────────────────┴───────────────┴──────────────┴────────────────────────────────────┘ + + +## Q7:通过对比上报距离与几何距离来检测可能的绕路 + +**真实场景:** 找出上报行驶距离明显超过两点直线距离的可疑行程,可能存在车费操纵嫌疑。 + +该查询通过比较行程上报的实际距离与上车点到下车点的直线距离,分析出租车和网约车行程偏离最短路径的程度。它会计算一个“绕路比”(detour ratio),用于反映实际路线比直线距离长多少。例如,比值为 1.5 表示该行程比直线距离多走了 50%。结果按绕路比从高到低排序,便于识别因交通、道路布局或其他原因而显著绕路的行程。 + +**被测试的空间查询特性:** + +1. 线几何的构建(ST_MakeLine) +2. 长度计算(ST_Length) +3. 坐标系转换和距离计算 +4. 基于几何与上报值之比的过滤 + + +```python +sd.sql(""" +WITH trip_lengths AS ( + SELECT + t.t_tripkey, + t.t_distance AS reported_distance_m, + ST_Length( + ST_MakeLine( + ST_GeomFromWKB(t.t_pickuploc), + ST_GeomFromWKB(t.t_dropoffloc) + ) + ) * 111111 AS line_distance_m -- 每度约对应的米数 + FROM trip t +) +SELECT + t.t_tripkey, + t.reported_distance_m, + t.line_distance_m, + t.reported_distance_m / NULLIF(t.line_distance_m, 0) AS detour_ratio +FROM trip_lengths t +ORDER BY + detour_ratio DESC NULLS LAST, + reported_distance_m DESC, + t_tripkey ASC +""").show(3) +``` + + ┌───────────┬─────────────────────┬────────────────────┬──────────────────────┐ + │ t_tripkey ┆ reported_distance_m ┆ line_distance_m ┆ detour_ratio │ + │ int64 ┆ decimal128 ┆ float64 ┆ float64 │ + ╞═══════════╪═════════════════════╪════════════════════╪══════════════════════╡ + │ 4688563 ┆ 0.00010 ┆ 11111.114941555596 ┆ 8.999996897341038e-9 │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 2380123 ┆ 0.00010 ┆ 11111.114983939786 ┆ 8.999996863009868e-9 │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 3077131 ┆ 0.00010 ┆ 11111.115027455284 ┆ 8.999996827762339e-9 │ + └───────────┴─────────────────────┴────────────────────┴──────────────────────┘ + + +## Q8:统计每栋建筑物 500 米半径内的上车次数 + +**真实场景:** 统计每栋建筑物 500 米范围内起始的行程数量。 + +该查询通过统计在每栋建筑物 500 米范围内起始的行程数量,识别哪些建筑物附近产生的出租车和网约车上车活动最多。它分析特定建筑物(如酒店、购物中心、机场或办公楼)与其周边乘车需求之间的关系。结果按数量排序,可以帮助识别出最重要的上车热点建筑物,并理解不同类型的建筑物如何影响交通需求。 + +**被测试的空间查询特性:** + +1. 点和多边形之间基于距离的空间连接 +2. 在空间连接结果上的聚合 + + +```python +sd.sql(""" +SELECT b.b_buildingkey, b.b_name, COUNT(*) AS nearby_pickup_count +FROM trip t +JOIN building b +ON ST_DWithin(ST_GeomFromWKB(t.t_pickuploc), ST_GeomFromWKB(b.b_boundary), 0.0045) -- 约 500m +GROUP BY b.b_buildingkey, b.b_name +ORDER BY nearby_pickup_count DESC, b.b_buildingkey ASC +""").show(3) +``` + + ┌───────────────┬────────┬─────────────────────┐ + │ b_buildingkey ┆ b_name ┆ nearby_pickup_count │ + │ int64 ┆ utf8 ┆ int64 │ + ╞═══════════════╪════════╪═════════════════════╡ + │ 3779 ┆ linen ┆ 42 │ + ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 19135 ┆ misty ┆ 36 │ + ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 4416 ┆ sienna ┆ 26 │ + └───────────────┴────────┴─────────────────────┘ + + +## Q9:通过 IoU 进行建筑物合并(检测重复/重叠的建筑物轮廓) + +**真实场景:** 检测 GIS 数据集中重复或重叠的建筑物轮廓,识别数据质量问题。 + +该查询通过计算建筑物轮廓之间的相互重叠面积来识别重叠的建筑物。对于每一对相互接触或相互重叠的建筑物,它会测量每栋建筑物的总面积以及它们的重叠面积,然后计算 0 到 1 之间的“交并比”(Intersection over Union,IoU)。结果按 IoU 从高到低排序,可揭示出最显著重叠的建筑物对,这有助于识别数据质量问题、相邻结构,或共享公共区域(如院子或停车场)的建筑物。 + +**被测试的空间查询特性:** + +1. 带空间相交的自连接(ST_Intersects) +2. 面积计算(ST_Area) +3. 几何相交操作(ST_Intersection) +4. 复杂几何比值的计算(IoU——交并比) + + +```python +sd.sql(""" +WITH b1 AS ( + SELECT b_buildingkey AS id, ST_GeomFromWKB(b_boundary) AS geom + FROM building +), +b2 AS ( + SELECT b_buildingkey AS id, ST_GeomFromWKB(b_boundary) AS geom + FROM building +), +pairs AS ( + SELECT + b1.id AS building_1, + b2.id AS building_2, + ST_Area(b1.geom) AS area1, + ST_Area(b2.geom) AS area2, + ST_Area(ST_Intersection(b1.geom, b2.geom)) AS overlap_area + FROM b1 + JOIN b2 ON b1.id < b2.id AND ST_Intersects(b1.geom, b2.geom) +) +SELECT + building_1, + building_2, + area1, + area2, + overlap_area, + CASE + WHEN (area1 + area2 - overlap_area) = 0 THEN 1.0 + ELSE overlap_area / (area1 + area2 - overlap_area) + END AS iou +FROM pairs +ORDER BY iou DESC, building_1 ASC, building_2 ASC +""").show(3) +``` + + ┌────────────┬────────────┬───┬───────────────────────┬────────────────────┐ + │ building_1 ┆ building_2 ┆ … ┆ overlap_area ┆ iou │ + │ int64 ┆ int64 ┆ ┆ float64 ┆ float64 │ + ╞════════════╪════════════╪═══╪═══════════════════════╪════════════════════╡ + │ 2285 ┆ 15719 ┆ … ┆ 2.3709162946727276e-6 ┆ 0.9056816071717889 │ + ├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 7562 ┆ 18534 ┆ … ┆ 5.855106543747764e-6 ┆ 0.8450437137796769 │ + ├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 2285 ┆ 13658 ┆ … ┆ 1.9770693222933237e-6 ┆ 0.737899157380637 │ + └────────────┴────────────┴───┴───────────────────────┴────────────────────┘ + + +## Q10:每个区域内起始行程的统计指标 + +**真实场景:** 分析每个行政区域(如市辖区或街区)的行程模式与性能指标。 + +该查询通过计算每个区域内起始行程的平均时长、平均距离和数量,分析各个地理区域的行程模式。它使用左连接(LEFT JOIN)来保留所有区域,包括那些没有上车活动的区域,从而展示出哪些街区平均行程较长,哪些则以较短的本地行程为主。结果按平均时长降序排序,便于识别人们倾向于走长途的区域——这些区域可能较为偏远、本地配套有限,或作为长途出行的出发地。 + +**被测试的空间查询特性:** + +1. 点在多边形内的空间连接(ST_Within) +2. 多指标聚合(平均时长、距离、数量) +3. 使用 LEFT JOIN 保留无行程的区域 + + +```python +sd.sql(""" +SELECT + z.z_zonekey, + z.z_name AS pickup_zone, + AVG(t.t_dropofftime - t.t_pickuptime) AS avg_duration, + AVG(t.t_distance) AS avg_distance, + COUNT(t.t_tripkey) AS num_trips +FROM + zone z + LEFT JOIN trip t + ON ST_Within( + ST_GeomFromWKB(t.t_pickuploc), ST_GeomFromWKB(z.z_boundary) + ) +GROUP BY z.z_zonekey, z.z_name +ORDER BY avg_duration DESC NULLS LAST, z.z_zonekey ASC +""").show(3) +``` + + ┌───────────┬────────────────┬────────────────────────────────────┬──────────────┬───────────┐ + │ z_zonekey ┆ pickup_zone ┆ avg_duration ┆ avg_distance ┆ num_trips │ + │ int64 ┆ utf8 ┆ duration ┆ decimal128 ┆ int64 │ + ╞═══════════╪════════════════╪════════════════════════════════════╪══════════════╪═══════════╡ + │ 31558 ┆ Benewah County ┆ 4 days 13 hours 3 mins 34.000 secs ┆ 0.002180000 ┆ 2 │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤ + │ 119540 ┆ Kreis Unna ┆ 2 days 4 hours 52 mins 44.000 secs ┆ 0.001050000 ┆ 1 │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤ + │ 59928 ┆ Ndhiwa ┆ 2 days 4 hours 19 mins 39.000 secs ┆ 0.001040000 ┆ 1 │ + └───────────┴────────────────┴────────────────────────────────────┴──────────────┴───────────┘ + + +## Q11:统计跨区域出行的行程数量 + +**真实场景:** 识别跨行政区或跨城市的行程,以了解跨边界的出行模式。 + +该查询通过判断行程的上车区域与下车区域是否相同,统计有多少行程跨越了区域边界。它会找出每个行程的上车区域和下车区域,然后仅保留上车区域与下车区域不同的行程。结果是跨区域行程的总数,可用于衡量在不同街区、行政区或区域之间发生的出行量,而非仅停留在同一本地区域内的出行量。 + +**被测试的空间查询特性:** + +1. 多次点在多边形内的空间连接 +2. 基于空间关系结果进行过滤 + + +```python +sd.sql(""" +SELECT COUNT(*) AS cross_zone_trip_count +FROM + trip t + JOIN zone pickup_zone + ON ST_Within( + ST_GeomFromWKB(t.t_pickuploc), + ST_GeomFromWKB(pickup_zone.z_boundary) + ) + JOIN zone dropoff_zone + ON ST_Within( + ST_GeomFromWKB(t.t_dropoffloc), + ST_GeomFromWKB(dropoff_zone.z_boundary) + ) +WHERE pickup_zone.z_zonekey != dropoff_zone.z_zonekey +""").show(3) +``` + + ┌───────────────────────┐ + │ cross_zone_trip_count │ + │ int64 │ + ╞═══════════════════════╡ + │ 176391 │ + └───────────────────────┘ + + +## Q12:使用 KNN 连接找出每个行程上车点最近的 5 栋建筑物 +**真实场景:** 找出每个行程起点最近的地标或建筑物,为定位和导航提供上下文。 + +该查询通过空间最近邻分析,找出每个行程上车点最近的 5 栋建筑物。对于每个行程,它会识别出与上车点地理距离最近的 5 栋建筑物,并计算到每栋建筑物的精确距离。结果可以揭示哪些建筑物常常出现在上车点附近,有助于理解行程起点与附近地标、商业设施或住宅建筑之间的关系,以及它们如何影响出行需求模式。 + +**被测试的空间查询特性:** + +1. K 近邻(KNN)空间连接 +2. 点和多边形之间的距离计算 +3. 基于空间邻近性进行排序与限制 + + +```python +sd.sql(""" +WITH trip_with_geom AS ( + SELECT + t_tripkey, + t_pickuploc, + ST_GeomFromWKB(t_pickuploc) as pickup_geom + FROM trip +), +building_with_geom AS ( + SELECT + b_buildingkey, + b_name, + b_boundary, + ST_GeomFromWKB(b_boundary) as boundary_geom + FROM building +) +SELECT + t.t_tripkey, + t.t_pickuploc, + b.b_buildingkey, + b.b_name AS building_name, + ST_Distance(t.pickup_geom, b.boundary_geom) AS distance_to_building +FROM trip_with_geom t +JOIN building_with_geom b + ON ST_KNN(t.pickup_geom, b.boundary_geom, 5, FALSE) +ORDER BY t.t_tripkey ASC, distance_to_building ASC, b.b_buildingkey ASC +""").show(3) +``` + + ┌───────────┬─────────────────────────────────┬───────────────┬───────────────┬────────────────────┐ + │ t_tripkey ┆ t_pickuploc ┆ b_buildingkey ┆ building_name ┆ distance_to_buildi │ + │ int64 ┆ binary ┆ int64 ┆ utf8 ┆ ng… │ + ╞═══════════╪═════════════════════════════════╪═══════════════╪═══════════════╪════════════════════╡ + │ 1 ┆ 01010000009f3c318dd43735405930… ┆ 15870 ┆ purple ┆ 0.984633987957188 │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 1 ┆ 01010000009f3c318dd43735405930… ┆ 6800 ┆ ghost ┆ 1.205725156670704 │ + ├╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤ + │ 1 ┆ 01010000009f3c318dd43735405930… ┆ 8384 ┆ lavender ┆ 1.4195012994942622 │ + └───────────┴─────────────────────────────────┴───────────────┴───────────────┴────────────────────┘ diff --git a/docs/quickstart.zh.md b/docs/quickstart.zh.md new file mode 100644 index 0000000..119b6c6 --- /dev/null +++ b/docs/quickstart.zh.md @@ -0,0 +1,121 @@ +--- +title: 快速开始 +--- + + + +## 安装 + +从源代码安装: + +```shell +git clone https://github.com/apache/sedona-spatialbench.git +cd sedona-spatialbench +cargo install --path spatialbench-cli +``` + +安装完成后,你应当能够运行: + +```shell +spatialbench-cli --help +``` + +## 生成 SF1 数据 + +以 Parquet 格式生成规模因子为 1 的完整数据集: + +```shell +spatialbench-cli --scale-factor 1 +``` + +该命令会生成六张表: + +* trip +* customer +* driver +* vehicle +* zone +* building + +默认情况下,输出会写入当前目录。 + +## 自定义输出文件 + +下面介绍几个常用的输出文件自定义选项。要查看全部可用选项,请运行 `spatialbench-cli --help`。 + +### 仅生成部分表 + +```shell +spatialbench-cli --scale-factor 1 --tables trip,building +``` + +### 将表输出分区为多个文件 + +手动指定分区数量: + +```shell +spatialbench-cli --scale-factor 10 --tables trip --parts 4 +``` + +或者让 CLI 根据目标文件大小来自动决定文件数量: + +```shell +spatialbench-cli --scale-factor 10 --mb-per-file 512 +``` + +### 设置输出目录 + +```shell +spatialbench-cli --scale-factor 1 --output-dir data/sf1 +``` + +### 直接生成到 S3 + +你可以通过将输出目录设置为 S3 URI,将数据直接生成到 Amazon S3 或兼容 S3 的存储中: + +```shell +# 设置 AWS 凭据 +export AWS_ACCESS_KEY_ID="your-access-key" +export AWS_SECRET_ACCESS_KEY="your-secret-key" +export AWS_REGION="us-west-2" # 必须与你的桶所在区域一致 + +# 生成数据到 S3 +spatialbench-cli --scale-factor 10 --mb-per-file 256 --output-dir s3://my-bucket/spatialbench/sf10 + +# 对于兼容 S3 的服务(如 MinIO 等) +export AWS_ENDPOINT="http://localhost:9000" +spatialbench-cli --scale-factor 1 --output-dir s3://my-bucket/data +``` + +S3 写入器采用流式分段上传(multipart upload),在上传分段前以 32 MB 的块对数据进行缓冲。所有标准的 AWS 环境变量均受支持,包括用于临时凭据的 `AWS_SESSION_TOKEN`。 + +## 配置空间数据分布 + +SpatialBench 使用一个空间数据生成器,按照真实的空间分布来生成合成的点和多边形数据。 + +要详细了解 SpatialBench 提供的各种空间分布,请参见[此处](https://sedona.apache.org/spatialbench/spatialbench-distributions/)。 + +有关空间分布的调优、完整的 YAML schema 与示例的更多细节,请参阅 [CONFIGURATION.md](https://github.com/apache/sedona-spatialbench/blob/main/spatialbench-cli/CONFIGURATION.md)。 + +你可以通过 `--config` 参数传入 YAML 文件,从而在运行时覆盖默认值: + +```shell +spatialbench-cli --scale-factor 1 --config spatialbench-config.yml +``` + +如果未提供 `--config`,SpatialBench 会检查 `./spatialbench-config.yml`。如果该文件也不存在,则回退到内置默认配置。 diff --git a/docs/release-notes.zh.md b/docs/release-notes.zh.md new file mode 100644 index 0000000..b74b0f4 --- /dev/null +++ b/docs/release-notes.zh.md @@ -0,0 +1,66 @@ + + +# 发布说明 + +## SpatialBench 0.2.0 + +### 主要亮点 + +* 支持 DuckDB 与 SedonaDB 的每日(nightly)基准测试 +* 在自动化基准测试框架中集成 Spatial Polars +* 基准测试输出支持写入 S3 +* 引入 pre-commit hook,并改进 CI + +### 新特性 + +* feature: Add DuckDB and SedonaDB nightly support (#76) +* feature: Add Spatial Polars to the automated benchmark framework (#73) +* feature: Add a benchmark GitHub Action to compare spatial libraries (#72) +* feat: Add S3 write support (#71) + +### Bug 修复 + +* spatial polars Q11 query fix (#75) +* Fix the failed Python build (#69) + +### 改进 + +* Unify navigation bar and theme with main Apache Sedona site (#88) +* Add basic EditorConfig file (#80) +* [CI] Add pre-commit hook to trim trailing whitespace (#79) +* [CI] Add pre-commit with basic checks (#77) +* [CI] Add Dependabot config for github-actions ecosystem (#84) +* docs: Add uncompressed data sizes of tables (#68) +* docs: Update docs and readme (#74) +* misc: Fix spelling and typos (#78, #81) + +## SpatialBench 0.1.0 + +这是 SpatialBench 的首个发布版本。SpatialBench 是一个空间数据处理基准测试套件,用于评估和比较各类空间数据处理库。 + +### 主要亮点 + +* 用于比较各类空间数据处理库的基准测试框架 +* 支持 Spatial Polars 基准测试查询 +* 可配置的输出文件大小和分区方式 +* 通过 HTTPS 从 Hugging Face 加载 Overture Divisions 数据 +* 强制几何有效性,并对 CCW 朝向和反子午线进行处理 +* 支持 PyPI 与 Cargo 的发布 +* 提供快速开始指南和贡献者指南文档 diff --git a/docs/requirements.txt b/docs/requirements.txt index 01da27b..65e0c0c 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -6,6 +6,7 @@ mkdocs-git-revision-date-localized-plugin mkdocs-glightbox mkdocs-macros-plugin mkdocs-material +mkdocs-static-i18n mkdocs-jupyter mkdocstrings[python] notebook diff --git a/docs/single-node-benchmarks.zh.md b/docs/single-node-benchmarks.zh.md new file mode 100644 index 0000000..bcaa2dc --- /dev/null +++ b/docs/single-node-benchmarks.zh.md @@ -0,0 +1,192 @@ +--- +title: SpatialBench 单节点基准测试 +--- + + + +本页面展示了 SpatialBench 在 SedonaDB、DuckDB 与 GeoPandas 上的单节点基准测试结果。该基准测试于 2025 年 9 月 22 日进行,所使用的版本为 SpatialBench v0.1.0 预发布版本(main 分支上的提交 `9094be8`)。 + +下面是 SpatialBench v0.1 在规模因子 1(SF1)和规模因子 10(SF10)下对查询 1–12 的运行结果。 + +![规模因子 1 的基准测试结果](image/sf1-09242025.png){ width="400" } +![规模因子 10 的基准测试结果](image/sf10-09242025.png){ width="400" } +{: .grid } + +## 硬件 + +该基准测试运行在 AWS EC2 `m7i.2xlarge` 实例上,配备 8 个 CPU 和 32 GB 内存。我们鼓励你尝试在不同的硬件配置上运行 SpatialBench,并与社区分享你的结果。 + +## 测试数据 + +数据集由 SpatialBench 的 dbgen 生成,并以纯 Parquet 格式存储在 AWS S3 存储桶中。几何列以 Well-Known Binary(WKB)编码存储,使用 Parquet 的 BINARY 类型。所有系统都直接从 S3 桶中读取 Parquet 文件,未涉及任何本地预加载。每个 Parquet row group 的大小为 128 MB。为了更贴近真实场景,大型 Parquet 文件会被拆分为多个较小的文件,每个约 200–300 MB。 + +我们在 `us-west-2` 区域提供规模因子为 1 和 10 的公开数据集。你可以通过以下路径访问: + +=== "规模因子 = 1" + + ```txt + s3://wherobots-examples/data/spatialbench/SpatialBench_sf1/building/ + s3://wherobots-examples/data/spatialbench/SpatialBench_sf1/customer/ + s3://wherobots-examples/data/spatialbench/SpatialBench_sf1/driver/ + s3://wherobots-examples/data/spatialbench/SpatialBench_sf1/trip/ + s3://wherobots-examples/data/spatialbench/SpatialBench_sf1/vehicle/ + s3://wherobots-examples/data/spatialbench/SpatialBench_sf1/zone/ + ``` + +=== "规模因子 = 10" + + ```txt + s3://wherobots-examples/data/spatialbench/SpatialBench_sf10/building/ + s3://wherobots-examples/data/spatialbench/SpatialBench_sf10/customer/ + s3://wherobots-examples/data/spatialbench/SpatialBench_sf10/driver/ + s3://wherobots-examples/data/spatialbench/SpatialBench_sf10/trip/ + s3://wherobots-examples/data/spatialbench/SpatialBench_sf10/vehicle/ + s3://wherobots-examples/data/spatialbench/SpatialBench_sf10/zone/ + ``` + +## 软件 + +本基准测试使用以下软件版本: + +* GeoPandas: 1.1.1 +* Shapely: 2.1.1 +* NumPy: 2.3.3 +* DuckDB: 1.4.0 +* SedonaDB: 0.1.0 + +本基准测试报告明确给出软件版本,便于追踪性能随时间的变化。除非另行说明,所有软件均使用默认设置。对于 DuckDB,我们显式将 `enable_external_file_cache` 设置为 `false`,以与其他引擎保持一致,重点关注冷启动查询的运行时间。 + +所记录的运行时间涵盖了每个引擎的整个查询执行过程,包括数据加载。我们对每个查询结果使用 `COUNT` 来触发完整执行,但没有将结果写入外部文件,以避免引入额外的写入开销。每个查询的超时阈值设为 `1200` 秒。 + +由于 GeoPandas 是单线程执行且缺乏查询优化器,任何并行化或优化都必须手动实现。在本基准测试中,我们采用与其他引擎运行的 SQL 查询相对应的直接 Python 实现。如果你是 GeoPandas 专家,欢迎与我们合作完成更优化或更并行化的版本。 + +## 结果分析 + +### 空间过滤与基础操作(Q1–Q6) + +DuckDB 和 SedonaDB 在 SF 1 和 SF 10 下均能达到类似的低延迟表现,而 GeoPandas 在更大规模时则力不从心。主要原因是 GeoPandas 缺乏查询优化器来选择高效的执行策略,且没有多核并行能力。相比之下,DuckDB 和 SedonaDB 利用列式数据布局、向量化执行、多核并行以及查询优化等技术,实现了较强的性能。不过,SedonaDB 在空间聚合(Q5)上仍存在挑战,DuckDB 在该项上表现明显更好。这是 SedonaDB 的一个已知问题,已列入改进计划。 + +### 几何计算(Q7–Q9) + +在交集/IoU(Q9)方面,SedonaDB 表现尤为出色,效率提升显著。这类查询主要关注面积计算、距离计算和空间相交等几何操作。 + +### 复杂空间连接与聚合(Q10–Q11) + +在更重的连接负载(特别是 Q10 和 Q11)上,SedonaDB 一直表现强劲,这得益于它的自适应空间连接策略——可基于空间统计为每个分区选择最合适的算法。DuckDB 在某些连接查询上表现良好,但在特定情形下会遇到扩展性问题;GeoPandas 能完成 SF 1,但无法完成 SF 10。 + +### 最近邻连接(Q12) + +SedonaDB 在 SF 1 和 SF 10 下均能完成 KNN 连接,这得益于其原生算子和优化算法。相比之下,DuckDB 和 GeoPandas 目前都没有内置的 KNN 连接支持。对于这些引擎,我们必须手工编写额外的代码,效率明显较低。未来若增加原生 KNN 能力,将有望帮助这两个引擎缩小这一差距。 + +### 综合表现 + +SedonaDB 在所有类型的查询上均表现均衡,并能有效扩展到 SF 10。DuckDB 在空间过滤和部分几何计算上表现出色,但在复杂连接和 KNN 查询上存在挑战。GeoPandas 虽在 Python 生态中广受欢迎,但需要手动优化和并行化才能有效处理较大规模的数据集。 + +## 自动化基准测试(GitHub Actions) + +我们在每次 Pull Request 时以及定期通过 GitHub Actions 运行自动化基准测试,以验证所有 SpatialBench 查询都能在受支持的引擎上完整运行。 + +!!! note "不适合用于性能对比" + GitHub Actions 上的基准测试旨在验证查询的正确性和可运行性,**不适用于**严肃的性能对比。GitHub Actions 运行器的性能存在波动,且资源有限。如需进行有意义的性能基准测试,请按上述章节的描述,使用合适的规模因子在专用硬件上运行 SpatialBench。 + +### 查看最新结果 + +访问 [GitHub Actions 基准测试页面](https://github.com/apache/sedona-spatialbench/actions/workflows/benchmark.yml),可查看最新结果。点击任一成功的工作流运行记录,并向下滚动至 **Summary** 部分,即可查看: + +- 各引擎的查询执行状态 +- 所有 12 个查询的对比情况 +- 错误与超时信息 + +### 支持的引擎 + +自动化测试覆盖以下引擎: + +- 🦆 **DuckDB** —— 进程内分析型数据库,带有空间扩展 +- 🐼 **GeoPandas** —— Python 地理空间数据分析库 +- 🌵 **SedonaDB** —— 高性能空间分析引擎 +- 🐻‍❄️ **Spatial Polars** —— Polars 数据帧的地理空间扩展 + +### 运行你自己的基准测试 + +你可以从 [Actions 标签页](https://github.com/apache/sedona-spatialbench/actions/workflows/benchmark.yml) 手动触发自动化测试,并可配置以下选项: + +- **规模因子**:0.1、1 或 10 +- **引擎**:选择参与测试的引擎 +- **查询超时**:为较长查询调整超时阈值(默认:60 秒) +- **每个查询的运行次数**:1、3 或 5 次(用于求平均,默认为 3) +- **依赖包版本**:固定特定版本或使用最新版本 + +## 基准测试代码 + +你可以在 [sedona-spatialbench GitHub](https://github.com/apache/sedona-spatialbench) 仓库中获取并运行基准测试代码。 + +你可以在本地以及云环境中生成数据集并运行基准测试。 + +该仓库包含一个 issue 追踪器,你可以在那里提交 bug 报告或建议代码改进。 + +## 原始基准测试性能数据 + +下表给出了详细的基准测试结果。所有时间单位均为秒。ERROR 表示软件因异常(例如内存不足)未能完成查询。TIMEOUT 表示查询运行超过 1200 秒仍未返回结果。 + +=== "规模因子 = 1" + + | 查询 | SedonaDB | DuckDB | GeoPandas | + |-------|----------|--------|-----------| + | q1 | 0.66 | 0.96 | 12.78 | + | q2 | 8.07 | 9.95 | 20.74 | + | q3 | 0.80 | 1.17 | 13.59 | + | q4 | 8.41 | 9.83 | 25.24 | + | q5 | 5.10 | 1.80 | 47.08 | + | q6 | 8.59 | 9.36 | 24.43 | + | q7 | 1.66 | 1.82 | 137.00 | + | q8 | 1.10 | 1.08 | 16.08 | + | q9 | 0.23 | 50.15 | 0.28 | + | q10 | 18.79 | 207.84 | 46.13 | + | q11 | 32.98 | TIMEOUT| 51.01 | + | q12 | 14.55 | ERROR | TIMEOUT | + + +=== "规模因子 = 10" + + | 查询 | SedonaDB | DuckDB | GeoPandas | + |-------|----------|--------|-----------| + | q1 | 3.04 | 4.58 | ERROR | + | q2 | 8.89 | 8.26 | ERROR | + | q3 | 4.09 | 5.17 | TIMEOUT | + | q4 | 7.52 | 8.51 | ERROR | + | q5 | 50.81 | 14.40 | ERROR | + | q6 | 9.11 | 10.67 | ERROR | + | q7 | 14.44 | 14.03 | ERROR | + | q8 | 7.24 | 7.57 | TIMEOUT | + | q9 | 0.38 | 942.98 | 0.49 | + | q10 | 42.02 | ERROR | ERROR | + | q11 | 97.52 | ERROR | ERROR | + | q12 | 145.66 | ERROR | TIMEOUT | + +## 未来工作 + +我们计划在未来工作中加入更多的引擎和数据库,例如: + +* `dask-geopandas`,用于在单节点的多核之间实现并行化 +* 一个 R 语言的地理空间引擎 + +如果你是上述任何技术的专家,欢迎主导该项目或与我们联系开展合作。 + +为了保持清晰和简洁,专为多节点环境设计的计算引擎被有意地排除在这些单节点结果之外。同样,像 PostGIS 这样的事务型数据库,其查询执行方式与纯 Python 引擎(如 GeoPandas)或分析型引擎(如 SedonaDB、DuckDB)有本质区别。由于 SpatialBench 主要聚焦于分析型工作负载,这些系统在当前研究中并未包含。 + +SpatialBench 倡议的总体目标,是为空间领域社区提供一套可靠的基准测试,并帮助推动更好的用户工具的快速发展。 diff --git a/docs/spatialbench-distributions.zh.md b/docs/spatialbench-distributions.zh.md new file mode 100644 index 0000000..6bc0711 --- /dev/null +++ b/docs/spatialbench-distributions.zh.md @@ -0,0 +1,106 @@ +--- +title: SpatialBench 数据分布 +--- + + + + +SpatialBench 提供了一组空间分布,用于生成具有不同偏斜程度和真实度的合成数据集。每种分布都有其独特的数学基础、参数以及典型的空间模式。所选分布直接决定了你的数据看起来是地图上均匀散布的点、集中的热点,还是分层的城市聚类。 + + +## Uniform(均匀分布) + +最简单的情形:每个点独立地从单位正方形 $[0,1]^2$ 上的均匀分布中抽取。 + +$$ +X \sim U(0,1), \quad Y \sim U(0,1) +$$ + +该分布没有可调参数。结果是均匀、平坦的分布——可以作为基线使用,但很少能反映任何真实的空间数据集。如果你的目标是在不引入偏斜干扰的情况下测试系统,那么这是一个不错的起点。 + + +## Normal(正态分布) + +正态分布会引入聚集特征。两个坐标都从可配置均值和标准差的高斯分布中抽取: + +$$ +X, Y \sim \mathcal{N}(\mu, \sigma^2), \quad \text{截断至 } [0,1] +$$ + +其中 `mu` 决定热点在正方形中的位置,`sigma` 决定扩散程度——较小的 `sigma` 会产生一个尖锐密集的聚类,较大的 sigma 则会使点更稀疏地分布在空间中。如果你希望模拟单个高密度活动中心(例如,在大片空白区域中只有一座城市的情况),这是合适的选择。其代价是它过于简单,无法建模多个热点或复杂的城市结构。 + + +## Diagonal(对角线分布) + +对角线分布在 x 与 y 之间强制引入相关性。以一定概率(probability)将点直接放置在 $y=x$ 的直线上,否则就用宽度由 buffer 控制的高斯噪声对点进行扰动。结果是一条紧贴对角线的点带。 + +这种模式在地理上并不真实,但对于需要已知相关结构的实验非常有用——例如,观察当坐标不独立时,索引或过滤的行为表现。 + + +## Bit(比特分布) + +比特分布通过对正方形进行递归二进制细分。每个比特位以概率 `probability` 切换,递归深度由 `digits` 决定。这会生成一组落入确定性网格结构的坐标,单元格是否被占据则取决于比特随机性。 + +结果看起来像一个不同分辨率的点阵。增大 digits 可以细化网格;降低 probability 则会让网格更稀疏。这种分布本质上是合成的,适用于对系统进行高度规整数据的压力测试。 + + +## Sierpinski(谢尔宾斯基分布) + +谢尔宾斯基模式来自“混沌游戏”,朝着三角形顶点反复迭代。经过多次迭代后,点会落入经典的自相似分形:一张布满嵌套三角形空洞的“地毯”。该分布没有可调参数。 + +虽然这种分布并不模拟任何自然过程,但它能生成极度偏斜的数据——密集区与大块空白交替出现,因此非常适合用来观察系统在面对病态聚集时的表现。 + + +## Thomas 过程 + +Thomas(高斯型 Neyman–Scott)过程通过分层生成父点和子点来产生热点。父点中心使用 Halton 序列进行确定性放置。每个父点会被分配一个从帕累托分布中抽取的权重,然后围绕该父点按标准差为 sigma 的高斯噪声生成子点。 + +关键参数: + +- `parents` 决定整体有多少个热点。 +- `mean_offspring` 用于缩放全局密度。 +- `sigma` 控制每个聚类的扩散程度。 +- `pareto_alpha` 与 `pareto_xm` 共同塑造聚类大小的偏斜度:较小的 alpha 值意味着少数父点拥有极大的聚类,而大多数父点的聚类规模较小。 + +结果是一幅热点不均匀的图景——有些极为繁忙,有些几乎无人。这使得该分布比单纯的均匀分布或正态分布更接近真实的行程或建筑物分布。 + + +## Hierarchical Thomas(层次化 Thomas) + +层次化(或嵌套)Thomas 过程在前者的基础上引入了两个层级。首先,按照从帕累托分布中抽取的城市权重选择一个“城市”。在被选中的城市内,子聚类(街区)的数量本身是随机的——服从均值给定、方差给定、并被 min/max 约束的正态分布。最后,再(同样按帕累托权重)选择一个子聚类,最终点从围绕该子聚类的高斯分布中抽取。 + +参数也呼应了这一结构: + +- `cities` 控制顶层枢纽(城市)的数量。 +- `sub_mean`、`sub_sd`、`sub_min`、`sub_max` 决定每个城市拥有多少个街区。 +- `sigma_city` 控制街区围绕城市中心的分散程度;`sigma_sub` 控制点围绕街区的分散程度。 +- 两组 `pareto_alpha`/`pareto_xm` 分别对城市规模和街区规模的偏斜度进行建模。 + +这种分布可以产生真实的多尺度模式:大城市拥有大量密集的街区,而小城镇只有少数稀疏的聚类。它能以单层过程无法实现的方式,捕捉真实聚居数据中分层的异质性。 + +## 参考文献 + +- **Spider 分布(Uniform、Normal、Bit、Sierpinski、Diagonal):** + - Puloma Katiyar, Tin Vu, Sara Migliorini, Alberto Belussi, Ahmed Eldawy. *SpiderWeb: A Spatial Data Generator on the Web*. [ACM SIGSPATIAL 2020](https://dl.acm.org/doi/10.1145/3397536.3422351), Seattle, WA. +- **Thomas / Neyman–Scott 聚类过程:** + - Thomas, M. (1949). *A Generalization of Poisson’s Binomial Limit For use in Ecology*. [*Biometrika*, *36*(1/2)](https://doi.org/10.2307/2332526), 18–25. +- Jerzy Neyman, Elizabeth L. Scott, *Statistical Approach to Problems of Cosmology*, [*Journal of the Royal Statistical Society: Series B (Methodological)*, Volume 20, Issue 1, January 1958](https://doi.org/10.1111/j.2517-6161.1958.tb00272.x), Pages 1–29 +- **点过程理论:** + - Illian, J., Penttinen, A., Stoyan, H., & Stoyan, D. (2008). *Statistical Analysis and Modelling of Spatial Point Patterns*. Wiley. +- **分形生成(Sierpinski):** + - Barnsley, M. F., & Demko, S. (1985). *Iterated function systems and the global construction of fractals*. [Proceedings of the Royal Society of London. Series A, 399(1817)](https://doi.org/10.1098/rspa.1985.0057), 243–275. diff --git a/mkdocs.yml b/mkdocs.yml index ea638a3..984fad4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -140,6 +140,39 @@ plugins: - mkdocs-jupyter - search - macros + - i18n: + docs_structure: suffix + fallback_to_default: true + reconfigure_material: true + reconfigure_search: true + languages: + - locale: en + default: true + name: English + build: true + - locale: zh + name: 中文 + build: true + site_name: SpatialBench + site_description: SpatialBench 是一个用于评估各类数据库系统中地理空间 SQL 分析查询性能的基准测试 + nav_translations: + Home: 首页 + SpatialBench: SpatialBench + Quickstart: 快速开始 + Methodology: 方法论 + Queries: 查询 + Datasets & Generators: 数据集与生成器 + Data Distributions: 数据分布 + Single Node Results: 单节点结果 + Contributors Guide: 贡献者指南 + Release Notes: 发布说明 + Blog: 博客 + Community: 社区 + Apache Software Foundation: Apache 软件基金会 + Framework: 框架 + SpatialBench Queries: SpatialBench 查询 + Get Involved: 参与贡献 + Sedona OSS Blog: Sedona 开源博客 - git-revision-date-localized: type: datetime - glightbox: