【发布时间】:2016-09-26 23:25:47
【问题描述】:
我在 Redshift 中有两个表,我正在尝试根据用户规范化的 IP 地址进行连接以获取邮政编码人口统计数据。通过规范化地址,我的意思是它与一个统一长度的字符串一致,该字符串去除了句点并且可以直接相互比较。例如,这在任何连接完成之前应用于所有 ips 并存储在表中:
lpad(split_part(ip, '.', 1), 3, '0') ||
lpad(split_part(ip, '.', 2), 3, '0') ||
lpad(split_part(ip, '.', 3), 3, '0') ||
lpad(split_part(ip, '.', 4), 3, '0')
所以209.170.151.71 将被转换为209170151071。
我有两张桌子。首先是 visitor_details,其中包含以下内容:
-----------------------------
| visitor_id | ip |
-----------------------------
| 1 | 209170151071 |
| 2 | 123170167071 |
... ...
| 50000000 | 001213020341 |
-----------------------------
我有一个名为 geo_ip 的表,其结构如下:
----------------------------------------
| start_ip | end_ip | zip |
----------------------------------------
|209170151071 | 209170151071 | 11101 |
|309170151071 | 409170151071 | 11102 |
... ... ...
|509170151071 | 609170151071 | 11103 |
----------------------------------------
我正在尝试运行以下查询:
WITH vd AS (
SELECT visitor_id,
ip_address as c_ip
FROM dev.visitor_details
)
SELECT
visitor_id,
c_ip,
g.*
FROM
vd
JOIN
dev.geo_ip g
ON vd.c_ip BETWEEN g.startip and g.endip
LIMIT 500;
geo ip 上的排序键是使用 startip 和 endip 的交错排序键。桌子似乎也没有歪斜。但是,运行查询会导致执行时间很长(从未完成)。查看说明,我看到以下内容:
XN Limit (cost=0.00..245.17 rows=500 width=238)
-> XN Nested Loop DS_BCAST_INNER (cost=0.00..18442148764959.20 rows=37610983146614 width=238)
Join Filter: ((("inner".startip)::text <= ("outer".ip_address)::text) AND (("inner".endip)::text >= ("outer".ip_address)::text))
-> XN Seq Scan on visitor_details (cost=0.00..596971.20 rows=59697120 width=72)
-> XN Seq Scan on geo_ip g (cost=0.00..56702.71 rows=5670271 width=166)
----- Nested Loop Join in the query plan - review the join predicates to avoid Cartesian products -----
更奇怪的是,如果我为连接硬编码一个 IP 地址,查询计划看起来很正常。
任何人都可以就如何优化表设置的查询以使其高效运行提出任何建议吗?
更新
我按照第一个响应的建议进行了更改,但我仍然看到嵌套循环。所有 IP 现在都是 bigint,并且删除了 with 语句。
explain SELECT
vd.visitor_id,
vd.ip_address,
gi.zip
FROM
dev.visitor_details2 vd
JOIN dev.geo_ip3 gi ON vd.ip BETWEEN gi.startip and gi.endip
LIMIT 500;
QUERY PLAN
---------------------------------------------------------------------------------------------------------
XN Limit (cost=0.00..136.62 rows=500 width=51)
-> XN Nested Loop DS_BCAST_INNER (cost=0.00..10276958524959.20 rows=37610983146614 width=51)
Join Filter: (("inner".startip <= "outer".ip) AND ("inner".endip >= "outer".ip))
-> XN Seq Scan on visitor_details2 vd (cost=0.00..596971.20 rows=59697120 width=52)
-> XN Seq Scan on geo_ip3 gi (cost=0.00..56702.71 rows=5670271 width=23)
----- Nested Loop Join in the query plan - review the join predicates to avoid Cartesian products -----
(6 rows)
更新 2 以下是确认它们都是 bigint 的表定义:
master=# \d dev.visitor_details2;
Table "dev.visitor_details2"
Column | Type | Modifiers
------------+------------------------+-----------
id | integer | not null
visitor_id | character varying(108) |
ip | bigint |
ip_address | character varying(192) |
domain | integer |
Indexes:
"visitor_details2_pkey" PRIMARY KEY, btree (id)
master=# \d dev.geo_ip3;
Table "dev.geo_ip3"
Column | Type | Modifiers
--------------+------------------------+-----------
startip | bigint |
endip | bigint |
country | character varying(16) |
region | character varying(32) |
city | character varying(32) |
zip | character varying(16) |
latitude | double precision |
longitude | double precision |
areacode | integer |
metrocode | integer |
timezone | character varying(32) |
isp | character varying(128) |
organization | character varying(128) |
netspeed | character varying(32) |
domain | character varying(128) |
【问题讨论】:
-
您的统计数据是最新的吗?每个表的行数是多少?你的桌子是如何分布的?
-
是的,我在解释之前对表运行了分析,将 analyze_threshold_percent 设置为 0 以强制分析运行。 visitor_details2 有 59697122 行,geo_ip3 有 5670271 行。 geo_ip3 表通过 startip 分发,visitor_details 表通过 visitor_id 分发。 RedShift 报告 geo_ip3 的偏差为 1.0000,visitor_details2 的偏差为 1.0064。两者的 pct_stats_off 都是 0.00,两者的 pct_unsorted 都是 0.00。
-
\d本身并不能提供完整的 DDL。您没有显示排序键、dist 键等。请问我们可以看到实际的创建表语句吗?
标签: amazon-redshift