跳到主要内容
版本: 最新版本-3.5

使用 Docker 部署 StarRocks

本教程涵盖

  • 在单个 Docker 容器中运行 StarRocks
  • 加载两个公共数据集,包括数据的基本转换
  • 使用 SELECT 和 JOIN 分析数据
  • 基本数据转换(ETL 中的 T

使用的数据由纽约市开放数据和国家环境信息中心提供。

这两个数据集都非常大,由于本教程旨在帮助您了解 StarRocks 的使用,因此我们不会加载过去 120 年的数据。您可以在分配给 Docker 的 4 GB RAM 的机器上运行 Docker 镜像并加载此数据。对于更大的容错和可扩展部署,我们有其他文档,稍后会提供。

本文档包含大量信息,开头部分是逐步的内容,结尾部分是技术细节。 这样做是为了按以下顺序服务于这些目的

  1. 允许读者在 StarRocks 中加载数据并分析该数据。
  2. 解释加载期间的数据转换的基础知识。

前提条件

Docker

  • Docker
  • 分配给 Docker 的 4 GB RAM
  • 分配给 Docker 的 10 GB 可用磁盘空间

SQL 客户端

您可以使用 Docker 环境中提供的 SQL 客户端,也可以使用系统上的 SQL 客户端。 许多与 MySQL 兼容的客户端都可以工作,本指南涵盖了 DBeaver 和 MySQL Workbench 的配置。

curl

curl 用于向 StarRocks 发出数据加载作业并下载数据集。 通过在操作系统提示符下运行 curlcurl.exe 来检查是否已安装它。 如果未安装 curl,请在此处获取 curl


术语

FE

前端节点负责元数据管理、客户端连接管理、查询规划和查询调度。每个 FE 在其内存中存储和维护元数据的完整副本,这保证了 FE 之间的无差别服务。

BE

后端节点负责数据存储和执行查询计划。


启动 StarRocks

docker run -p 9030:9030 -p 8030:8030 -p 8040:8040 -itd \
--name quickstart starrocks/allin1-ubuntu

SQL 客户端

这三个客户端已经过本教程的测试,您只需要一个

  • mysql CLI:您可以从 Docker 环境或您的机器运行它。
  • DBeaver 可作为社区版和 Pro 版提供。
  • MySQL Workbench

配置客户端

使用 mysql CLI 的最简单方法是从 StarRocks 容器 starrocks-fe 运行它

docker exec -it quickstart \
mysql -P 9030 -h 127.0.0.1 -u root --prompt="StarRocks > "

如果您想安装 mysql CLI,请展开下面的 mysql client install

mysql 客户端安装
  • macOS:如果您使用 Homebrew 并且不需要 MySQL Server,请运行 brew install mysql 以安装 CLI。
  • Linux:检查您的存储库系统以获取 mysql 客户端。例如,yum install mariadb
  • Microsoft Windows:安装 MySQL Community Server 并运行提供的客户端,或从 WSL 运行 mysql

下载数据

将这两个数据集下载到您的机器。 您可以将它们下载到运行 Docker 的主机,无需在容器内下载。

纽约市崩溃数据

curl -O https://raw.githubusercontent.com/StarRocks/demo/master/documentation-samples/quickstart/datasets/NYPD_Crash_Data.csv

天气数据

curl -O https://raw.githubusercontent.com/StarRocks/demo/master/documentation-samples/quickstart/datasets/72505394728.csv

使用 SQL 客户端连接到 StarRocks

提示

如果您使用 mysql CLI 以外的客户端,请立即打开它。

此命令将在 Docker 容器中运行 mysql 命令

docker exec -it quickstart \
mysql -P 9030 -h 127.0.0.1 -u root --prompt="StarRocks > "

创建一些表

创建数据库

StarRocks > 提示符下键入这两行,然后在每行后按 Enter

CREATE DATABASE IF NOT EXISTS quickstart;

USE quickstart;

创建两个表

Crashdata

崩溃数据集包含比这些更多的字段,模式已缩减为仅包含可能有助于回答天气对驾驶条件影响的问题的字段。

CREATE TABLE IF NOT EXISTS crashdata (
CRASH_DATE DATETIME,
BOROUGH STRING,
ZIP_CODE STRING,
LATITUDE INT,
LONGITUDE INT,
LOCATION STRING,
ON_STREET_NAME STRING,
CROSS_STREET_NAME STRING,
OFF_STREET_NAME STRING,
CONTRIBUTING_FACTOR_VEHICLE_1 STRING,
CONTRIBUTING_FACTOR_VEHICLE_2 STRING,
COLLISION_ID INT,
VEHICLE_TYPE_CODE_1 STRING,
VEHICLE_TYPE_CODE_2 STRING
);

Weatherdata

与崩溃数据类似,天气数据集有更多的列(总共 125 列),只有预计回答问题的列包含在数据库中。

CREATE TABLE IF NOT EXISTS weatherdata (
DATE DATETIME,
NAME STRING,
HourlyDewPointTemperature STRING,
HourlyDryBulbTemperature STRING,
HourlyPrecipitation STRING,
HourlyPresentWeatherType STRING,
HourlyPressureChange STRING,
HourlyPressureTendency STRING,
HourlyRelativeHumidity STRING,
HourlySkyConditions STRING,
HourlyVisibility STRING,
HourlyWetBulbTemperature STRING,
HourlyWindDirection STRING,
HourlyWindGustSpeed STRING,
HourlyWindSpeed STRING
);

加载两个数据集

有很多方法可以将数据加载到 StarRocks 中。 对于本教程,最简单的方法是使用 curl 和 StarRocks Stream Load。

提示

打开一个新的 shell,因为这些 curl 命令是在操作系统提示符下运行的,而不是在 mysql 客户端中运行。 这些命令引用您下载的数据集,因此请从下载文件的目录运行它们。

系统将提示您输入密码。 您可能尚未为 MySQL root 用户分配密码,只需按 Enter 键即可。

curl 命令看起来很复杂,但它们将在本教程的末尾详细解释。现在,我们建议运行命令并运行一些 SQL 来分析数据,然后在最后阅读有关数据加载详细信息的信息。

纽约市碰撞数据 - 碰撞事故

curl --location-trusted -u root             \
-T ./NYPD_Crash_Data.csv \
-H "label:crashdata-0" \
-H "column_separator:," \
-H "skip_header:1" \
-H "enclose:\"" \
-H "max_filter_ratio:1" \
-H "columns:tmp_CRASH_DATE, tmp_CRASH_TIME, CRASH_DATE=str_to_date(concat_ws(' ', tmp_CRASH_DATE, tmp_CRASH_TIME), '%m/%d/%Y %H:%i'),BOROUGH,ZIP_CODE,LATITUDE,LONGITUDE,LOCATION,ON_STREET_NAME,CROSS_STREET_NAME,OFF_STREET_NAME,NUMBER_OF_PERSONS_INJURED,NUMBER_OF_PERSONS_KILLED,NUMBER_OF_PEDESTRIANS_INJURED,NUMBER_OF_PEDESTRIANS_KILLED,NUMBER_OF_CYCLIST_INJURED,NUMBER_OF_CYCLIST_KILLED,NUMBER_OF_MOTORIST_INJURED,NUMBER_OF_MOTORIST_KILLED,CONTRIBUTING_FACTOR_VEHICLE_1,CONTRIBUTING_FACTOR_VEHICLE_2,CONTRIBUTING_FACTOR_VEHICLE_3,CONTRIBUTING_FACTOR_VEHICLE_4,CONTRIBUTING_FACTOR_VEHICLE_5,COLLISION_ID,VEHICLE_TYPE_CODE_1,VEHICLE_TYPE_CODE_2,VEHICLE_TYPE_CODE_3,VEHICLE_TYPE_CODE_4,VEHICLE_TYPE_CODE_5" \
-XPUT https://:8030/api/quickstart/crashdata/_stream_load

这是前面命令的输出。 第一个突出显示的部分显示了您应该看到的内容(OK 和插入了除一行之外的所有行)。 一行被过滤掉,因为它不包含正确的列数。

Enter host password for user 'root':
{
"TxnId": 2,
"Label": "crashdata-0",
"Status": "Success",
"Message": "OK",
"NumberTotalRows": 423726,
"NumberLoadedRows": 423725,
"NumberFilteredRows": 1,
"NumberUnselectedRows": 0,
"LoadBytes": 96227746,
"LoadTimeMs": 1013,
"BeginTxnTimeMs": 21,
"StreamLoadPlanTimeMs": 63,
"ReadDataTimeMs": 563,
"WriteDataTimeMs": 870,
"CommitAndPublishTimeMs": 57,
"ErrorURL": "http://127.0.0.1:8040/api/_load_error_log?file=error_log_da41dd88276a7bfc_739087c94262ae9f"
}%

如果出现错误,输出会提供一个 URL 来查看错误消息。 在浏览器中打开它以找出发生了什么。 展开详细信息以查看错误消息

在浏览器中读取错误消息
Error: Value count does not match column count. Expect 29, but got 32.

Column delimiter: 44,Row delimiter: 10.. Row: 09/06/2015,14:15,,,40.6722269,-74.0110059,"(40.6722269, -74.0110059)",,,"R/O 1 BEARD ST. ( IKEA'S
09/14/2015,5:30,BRONX,10473,40.814551,-73.8490955,"(40.814551, -73.8490955)",TORRY AVENUE ,NORTON AVENUE ,,0,0,0,0,0,0,0,0,Driver Inattention/Distraction,Unspecified,,,,3297457,PASSENGER VEHICLE,PASSENGER VEHICLE,,,

天气数据

以与加载碰撞数据相同的方式加载天气数据集。

curl --location-trusted -u root             \
-T ./72505394728.csv \
-H "label:weather-0" \
-H "column_separator:," \
-H "skip_header:1" \
-H "enclose:\"" \
-H "max_filter_ratio:1" \
-H "columns: STATION, DATE, LATITUDE, LONGITUDE, ELEVATION, NAME, REPORT_TYPE, SOURCE, HourlyAltimeterSetting, HourlyDewPointTemperature, HourlyDryBulbTemperature, HourlyPrecipitation, HourlyPresentWeatherType, HourlyPressureChange, HourlyPressureTendency, HourlyRelativeHumidity, HourlySkyConditions, HourlySeaLevelPressure, HourlyStationPressure, HourlyVisibility, HourlyWetBulbTemperature, HourlyWindDirection, HourlyWindGustSpeed, HourlyWindSpeed, Sunrise, Sunset, DailyAverageDewPointTemperature, DailyAverageDryBulbTemperature, DailyAverageRelativeHumidity, DailyAverageSeaLevelPressure, DailyAverageStationPressure, DailyAverageWetBulbTemperature, DailyAverageWindSpeed, DailyCoolingDegreeDays, DailyDepartureFromNormalAverageTemperature, DailyHeatingDegreeDays, DailyMaximumDryBulbTemperature, DailyMinimumDryBulbTemperature, DailyPeakWindDirection, DailyPeakWindSpeed, DailyPrecipitation, DailySnowDepth, DailySnowfall, DailySustainedWindDirection, DailySustainedWindSpeed, DailyWeather, MonthlyAverageRH, MonthlyDaysWithGT001Precip, MonthlyDaysWithGT010Precip, MonthlyDaysWithGT32Temp, MonthlyDaysWithGT90Temp, MonthlyDaysWithLT0Temp, MonthlyDaysWithLT32Temp, MonthlyDepartureFromNormalAverageTemperature, MonthlyDepartureFromNormalCoolingDegreeDays, MonthlyDepartureFromNormalHeatingDegreeDays, MonthlyDepartureFromNormalMaximumTemperature, MonthlyDepartureFromNormalMinimumTemperature, MonthlyDepartureFromNormalPrecipitation, MonthlyDewpointTemperature, MonthlyGreatestPrecip, MonthlyGreatestPrecipDate, MonthlyGreatestSnowDepth, MonthlyGreatestSnowDepthDate, MonthlyGreatestSnowfall, MonthlyGreatestSnowfallDate, MonthlyMaxSeaLevelPressureValue, MonthlyMaxSeaLevelPressureValueDate, MonthlyMaxSeaLevelPressureValueTime, MonthlyMaximumTemperature, MonthlyMeanTemperature, MonthlyMinSeaLevelPressureValue, MonthlyMinSeaLevelPressureValueDate, MonthlyMinSeaLevelPressureValueTime, MonthlyMinimumTemperature, MonthlySeaLevelPressure, MonthlyStationPressure, MonthlyTotalLiquidPrecipitation, MonthlyTotalSnowfall, MonthlyWetBulb, AWND, CDSD, CLDD, DSNW, HDSD, HTDD, NormalsCoolingDegreeDay, NormalsHeatingDegreeDay, ShortDurationEndDate005, ShortDurationEndDate010, ShortDurationEndDate015, ShortDurationEndDate020, ShortDurationEndDate030, ShortDurationEndDate045, ShortDurationEndDate060, ShortDurationEndDate080, ShortDurationEndDate100, ShortDurationEndDate120, ShortDurationEndDate150, ShortDurationEndDate180, ShortDurationPrecipitationValue005, ShortDurationPrecipitationValue010, ShortDurationPrecipitationValue015, ShortDurationPrecipitationValue020, ShortDurationPrecipitationValue030, ShortDurationPrecipitationValue045, ShortDurationPrecipitationValue060, ShortDurationPrecipitationValue080, ShortDurationPrecipitationValue100, ShortDurationPrecipitationValue120, ShortDurationPrecipitationValue150, ShortDurationPrecipitationValue180, REM, BackupDirection, BackupDistance, BackupDistanceUnit, BackupElements, BackupElevation, BackupEquipment, BackupLatitude, BackupLongitude, BackupName, WindEquipmentChangeDate" \
-XPUT https://:8030/api/quickstart/weatherdata/_stream_load

回答一些问题

这些查询可以在您的 SQL 客户端中运行。所有查询都使用 quickstart 数据库。

USE quickstart;

纽约市每小时发生多少起碰撞事故?

SELECT COUNT(*),
date_trunc("hour", crashdata.CRASH_DATE) AS Time
FROM crashdata
GROUP BY Time
ORDER BY Time ASC
LIMIT 200;

这是部分输出。请注意,我正在更仔细地查看 1 月 6 日和 7 日,因为这是非节假日周的星期一和星期二。查看元旦可能无法表明早高峰时段的正常情况。

|       14 | 2014-01-06 06:00:00 |
| 16 | 2014-01-06 07:00:00 |
| 43 | 2014-01-06 08:00:00 |
| 44 | 2014-01-06 09:00:00 |
| 21 | 2014-01-06 10:00:00 |
| 28 | 2014-01-06 11:00:00 |
| 34 | 2014-01-06 12:00:00 |
| 31 | 2014-01-06 13:00:00 |
| 35 | 2014-01-06 14:00:00 |
| 36 | 2014-01-06 15:00:00 |
| 33 | 2014-01-06 16:00:00 |
| 40 | 2014-01-06 17:00:00 |
| 35 | 2014-01-06 18:00:00 |
| 23 | 2014-01-06 19:00:00 |
| 16 | 2014-01-06 20:00:00 |
| 12 | 2014-01-06 21:00:00 |
| 17 | 2014-01-06 22:00:00 |
| 14 | 2014-01-06 23:00:00 |
| 10 | 2014-01-07 00:00:00 |
| 4 | 2014-01-07 01:00:00 |
| 1 | 2014-01-07 02:00:00 |
| 3 | 2014-01-07 03:00:00 |
| 2 | 2014-01-07 04:00:00 |
| 6 | 2014-01-07 06:00:00 |
| 16 | 2014-01-07 07:00:00 |
| 41 | 2014-01-07 08:00:00 |
| 37 | 2014-01-07 09:00:00 |
| 33 | 2014-01-07 10:00:00 |

在周一或周二早高峰时段,大约有 40 起事故,17:00 时段也大约有 40 起事故。

纽约市的平均气温是多少?

SELECT avg(HourlyDryBulbTemperature),
date_trunc("hour", weatherdata.DATE) AS Time
FROM weatherdata
GROUP BY Time
ORDER BY Time ASC
LIMIT 100;

输出

请注意,这是 2014 年的数据,纽约市最近没有这么冷。

+-------------------------------+---------------------+
| avg(HourlyDryBulbTemperature) | Time |
+-------------------------------+---------------------+
| 25 | 2014-01-01 00:00:00 |
| 25 | 2014-01-01 01:00:00 |
| 24 | 2014-01-01 02:00:00 |
| 24 | 2014-01-01 03:00:00 |
| 24 | 2014-01-01 04:00:00 |
| 24 | 2014-01-01 05:00:00 |
| 25 | 2014-01-01 06:00:00 |
| 26 | 2014-01-01 07:00:00 |

在纽约市,能见度差时驾驶安全吗?

让我们看一下能见度较差(0 到 1.0 英里之间)时的崩溃次数。要回答这个问题,请使用 DATETIME 列在两个表上进行 JOIN。

SELECT COUNT(DISTINCT c.COLLISION_ID) AS Crashes,
truncate(avg(w.HourlyDryBulbTemperature), 1) AS Temp_F,
truncate(avg(w.HourlyVisibility), 2) AS Visibility,
max(w.HourlyPrecipitation) AS Precipitation,
date_format((date_trunc("hour", c.CRASH_DATE)), '%d %b %Y %H:%i') AS Hour
FROM crashdata c
LEFT JOIN weatherdata w
ON date_trunc("hour", c.CRASH_DATE)=date_trunc("hour", w.DATE)
WHERE w.HourlyVisibility BETWEEN 0.0 AND 1.0
GROUP BY Hour
ORDER BY Crashes DESC
LIMIT 100;

在低能见度的单个小时内,最高的崩溃次数为 129。有多个事项需要考虑

  • 2014 年 2 月 3 日是星期一
  • 上午 8 点是早高峰
  • 当时正在下雨(每小时 0.12 英寸或降水)
  • 温度为 32 华氏度(水的冰点)
  • 能见度在 0.25 英里处较差,纽约市的正常能见度为 10 英里
+---------+--------+------------+---------------+-------------------+
| Crashes | Temp_F | Visibility | Precipitation | Hour |
+---------+--------+------------+---------------+-------------------+
| 129 | 32 | 0.25 | 0.12 | 03 Feb 2014 08:00 |
| 114 | 32 | 0.25 | 0.12 | 03 Feb 2014 09:00 |
| 104 | 23 | 0.33 | 0.03 | 09 Jan 2015 08:00 |
| 96 | 26.3 | 0.33 | 0.07 | 01 Mar 2015 14:00 |
| 95 | 26 | 0.37 | 0.12 | 01 Mar 2015 15:00 |
| 93 | 35 | 0.75 | 0.09 | 18 Jan 2015 09:00 |
| 92 | 31 | 0.25 | 0.12 | 03 Feb 2014 10:00 |
| 87 | 26.8 | 0.5 | 0.09 | 01 Mar 2015 16:00 |
| 85 | 55 | 0.75 | 0.20 | 23 Dec 2015 17:00 |
| 85 | 20 | 0.62 | 0.01 | 06 Jan 2015 11:00 |
| 83 | 19.6 | 0.41 | 0.04 | 05 Mar 2015 13:00 |
| 80 | 20 | 0.37 | 0.02 | 06 Jan 2015 10:00 |
| 76 | 26.5 | 0.25 | 0.06 | 05 Mar 2015 09:00 |
| 71 | 26 | 0.25 | 0.09 | 05 Mar 2015 10:00 |
| 71 | 24.2 | 0.25 | 0.04 | 05 Mar 2015 11:00 |

在冰冷条件下驾驶怎么样?

水蒸气可以在 40 华氏度下升华为冰;此查询查看 0 到 40 华氏度之间的温度。

SELECT COUNT(DISTINCT c.COLLISION_ID) AS Crashes,
truncate(avg(w.HourlyDryBulbTemperature), 1) AS Temp_F,
truncate(avg(w.HourlyVisibility), 2) AS Visibility,
max(w.HourlyPrecipitation) AS Precipitation,
date_format((date_trunc("hour", c.CRASH_DATE)), '%d %b %Y %H:%i') AS Hour
FROM crashdata c
LEFT JOIN weatherdata w
ON date_trunc("hour", c.CRASH_DATE)=date_trunc("hour", w.DATE)
WHERE w.HourlyDryBulbTemperature BETWEEN 0.0 AND 40.5
GROUP BY Hour
ORDER BY Crashes DESC
LIMIT 100;

冰点温度的结果让我有点惊讶,我没想到在寒冷的 1 月的星期天早上,城市里会有太多的交通。 快速查看 weather.com 表明那天有一场大风暴,发生了很多碰撞事故,就像在数据中看到的那样。

+---------+--------+------------+---------------+-------------------+
| Crashes | Temp_F | Visibility | Precipitation | Hour |
+---------+--------+------------+---------------+-------------------+
| 192 | 34 | 1.5 | 0.09 | 18 Jan 2015 08:00 |
| 170 | 21 | NULL | | 21 Jan 2014 10:00 |
| 145 | 19 | NULL | | 21 Jan 2014 11:00 |
| 138 | 33.5 | 5 | 0.02 | 18 Jan 2015 07:00 |
| 137 | 21 | NULL | | 21 Jan 2014 09:00 |
| 129 | 32 | 0.25 | 0.12 | 03 Feb 2014 08:00 |
| 114 | 32 | 0.25 | 0.12 | 03 Feb 2014 09:00 |
| 104 | 23 | 0.7 | 0.04 | 09 Jan 2015 08:00 |
| 98 | 16 | 8 | 0.00 | 06 Mar 2015 08:00 |
| 96 | 26.3 | 0.33 | 0.07 | 01 Mar 2015 14:00 |

小心驾驶!


摘要

在本教程中,您

  • 在 Docker 中部署了 StarRocks
  • 加载了纽约市提供的崩溃数据和 NOAA 提供的天气数据
  • 使用 SQL JOIN 分析数据,以发现在低能见度或结冰的街道上驾驶是一个坏主意

还有更多内容需要学习; 我们有意掩盖了在 Stream Load 期间完成的数据转换。 有关详细信息,请参阅下面的 curl 命令说明。


curl 命令的注释

StarRocks Stream Load 和 curl 采用许多参数。此处仅描述本教程中使用的参数,其余参数将在更多信息部分中链接。

--location-trusted

这会将 curl 配置为将凭据传递给任何重定向的 URL。

-u root

用于登录 StarRocks 的用户名

-T filename

T 代表传输,要传输的文件名。

label:name-num

与此 Stream Load 作业关联的标签。标签必须是唯一的,因此如果您多次运行作业,则可以添加一个数字并不断递增它。

column_separator:,

如果您加载的文件使用单个 ,,则如上所示设置它,如果您使用不同的分隔符,则在此处设置该分隔符。常见的选择是 \t,|

skip_header:1

一些 CSV 文件具有一个包含所有列名列表的单个标题行,一些添加了带有数据类型的第二行。如果您有一行或两行标题行,则将 skip_header 设置为 12,如果没有标题行,则将其设置为 0

enclose:\"

通常使用双引号将包含嵌入逗号的字符串括起来。 本教程中使用的示例数据集具有包含逗号的地理位置,因此 enclose 设置设置为 \"。 请记住用 \ 转义 "

max_filter_ratio:1

这允许数据中存在一些错误。理想情况下,应将其设置为 0,并且作业会在出现任何错误时失败。将其设置为 1 以允许所有行在调试期间失败。

columns:

CSV 文件列到 StarRocks 表列的映射。您会注意到 CSV 文件中的列比表中的列多得多。将跳过未包含在表中的任何列。

您还会注意到,碰撞事故数据集的 columns: 行中包含一些数据转换。 在 CSV 文件中找到不符合标准的日期和时间是很常见的。 这是用于将碰撞发生时间和日期的 CSV 数据转换为 DATETIME 类型的逻辑

列行

这是一个数据记录的开头。日期格式为 MM/DD/YYYY,时间为 HH:MI。由于 DATETIME 通常为 YYYY-MM-DD HH:MI:SS,因此我们需要转换此数据。

08/05/2014,9:10,BRONX,10469,40.8733019,-73.8536375,"(40.8733019, -73.8536375)",

这是 columns: 参数的开头

-H "columns:tmp_CRASH_DATE, tmp_CRASH_TIME, CRASH_DATE=str_to_date(concat_ws(' ', tmp_CRASH_DATE, tmp_CRASH_TIME), '%m/%d/%Y %H:%i')

这指示 StarRocks

  • 将 CSV 文件的第一列的内容分配给 tmp_CRASH_DATE
  • 将 CSV 文件的第二列的内容分配给 tmp_CRASH_TIME
  • concat_ws()tmp_CRASH_DATEtmp_CRASH_TIME 连接在一起,并在它们之间留一个空格
  • str_to_date() 从连接的字符串创建一个 DATETIME
  • 将生成的 DATETIME 存储在 CRASH_DATE 列中

更多信息

StarRocks 表设计

Stream Load

机动车辆碰撞 - 碰撞事故 数据集由纽约市根据这些 使用条款隐私政策 提供。

本地气候数据(LCD) 由 NOAA 提供,并附有此 免责声明 和此 隐私政策