【发布时间】:2021-10-09 10:05:10
【问题描述】:
我有两个表,表 A 是 500gb+ 的人员信息表(以 id 为中心)。表 B 是仅包含表 A 中的 ID 和公共 URL 列(Facebook、Linkedin 等)(聚集在 publicURL 和 tblA_id 上)的窄查找表。这些 URL 在表 A 中,但在记录内的数组中,因此我无法对其进行聚类。
我想我可以使用表 B 来搜索表 A,只需要一个连接和“在 (URL1、URL2、URL3、URL4) 中的 URL 位置”。这最初效果很好。它将查询量从数百 GB 减少到了几个 100 MB。
问题:不能保证查询的 URL 会在表格中。如果找到至少一个 URL,则通常花费 100mb 或多或少,但如果使用未知 URL 或括号内的 NULL 执行查询,则会执行整个表扫描并花费 500gb。
我已经用几种方法编写了这个查询,无论如何问题都存在。我试过的:
SELECT
A.*
FROM TableB AS B
JOIN TableA AS A
ON A.id = B.tblA_id
WHERE B.public_url IN (
"linkedin.com/in/bingcrosby",
"linkedin.com/in/hillaryclinton",
"facebook.com/billhicks"
);
有同样问题的其他选项:
SELECT
A.*
FROM TableA AS A
WHERE id IN (
SELECT tblA_id
FROM TableB
WHERE public_url IN (
"linkedin.com/in/bingcrosby",
"linkedin.com/in/hillaryclinton",
"facebook.com/billhicks"
)
);
只要找到至少一个公共 URL,这两种方法都可以廉价而高效地工作。如果使用表 B 中的某些未知 URL,如何防止整个表扫描?即使我可以从子查询中生成错误,我也会很高兴。
感谢您的建议。这开始变得昂贵了。
【问题讨论】:
-
一种选择是在 URL 上或按 URL 的一部分进行分区。
-
有趣的想法,比如 ABS(MOD(FARM_FINGERPRINT(B.public_url), number_of_partitions))?这应该限制表扫描。但是,我们必须将它应用于 URL 的输入数组,这意味着动态 SQL,不是吗?我总是发现这对可读性和维护很不利。我想我可以使用 WITH 准临时表将其最小化。
-
。 .是的,您需要将相同的函数应用于输入进行比较。如果您使用散列(如您的示例),则仍需要进行实际比较,以防万一发生冲突。
-
Welp,试过这个。同样的问题。它一直想无条件地加入所有表 A。在这一点上,这似乎是一个错误。 ``` SELECT A.full_name FROM TableB AS B JOIN TableA AS A ON A.id = B.TblA_id AND B.url_partition IN (ABS(MOD(FARM_FINGERPRINT("facebook.com/billhicks"),4000)) ) WHERE B .public_url IN(“facebook.com/billhicks”)```
标签: sql google-cloud-platform google-bigquery