我正在处理https://dev.maxmind.com/geoip/geoip2/geolite2/
中csv格式的数据。
通常,是从ip块映射到asn和国家/地区的数据。
我有2个表,它们都是Memory
引擎,第一个有299727条记录,第二个有406685条记录。
SELECT *
FROM __ip_block_to_country
LIMIT 5
┌─network────┬───────id─┬───min_ip─┬───max_ip─┬─geoname_id─┬─country_iso_code─┬─country_name─┐
│ 1.0.0.0/24 │ 16777216 │ 16777217 │ 16777472 │ 2077456 │ AU │ Australia │
│ 1.0.1.0/24 │ 16777472 │ 16777473 │ 16777728 │ 1814991 │ CN │ China │
│ 1.0.2.0/23 │ 16777728 │ 16777729 │ 16778240 │ 1814991 │ CN │ China │
│ 1.0.4.0/22 │ 16778240 │ 16778241 │ 16779264 │ 2077456 │ AU │ Australia │
│ 1.0.8.0/21 │ 16779264 │ 16779265 │ 16781312 │ 1814991 │ CN │ China │
└────────────┴──────────┴──────────┴──────────┴────────────┴──────────────────┴──────────────┘
SELECT *
FROM __ip_block_to_asn
LIMIT 5
┌─network──────┬─autonomous_system_number─┬─autonomous_system_organization─┬───────id─┬─subnet_count─┬───min_ip─┬───max_ip─┐
│ 1.0.0.0/24 │ 13335 │ Cloudflare Inc │ 16777216 │ 255 │ 16777217 │ 16777472 │
│ 1.0.4.0/22 │ 56203 │ Gtelecom-AUSTRALIA │ 16778240 │ 1023 │ 16778241 │ 16779264 │
│ 1.0.16.0/24 │ 2519 │ ARTERIA Networks Corporation │ 16781312 │ 255 │ 16781313 │ 16781568 │
│ 1.0.64.0/18 │ 18144 │ Energia Communications,Inc. │ 16793600 │ 16383 │ 16793601 │ 16809984 │
│ 1.0.128.0/17 │ 23969 │ TOT Public Company Limited │ 16809984 │ 32767 │ 16809985 │ 16842752 │
└──────────────┴──────────────────────────┴────────────────────────────────┴──────────┴──────────────┴──────────┴──────────┘
现在,我想检查哪个国家涵盖一个asn的整个IP池。以下查询仅用于获取法定国家/地区的索引。
SELECT idx from(
SELECT
(
SELECT groupArray(min_ip),groupArray(max_ip),groupArray(country_iso_code),groupArray(country_name)
FROM __ip_block_to_country
) t,
arrayFilter((i,mii, mai) -> min_ip >= mii and max_ip <= mai, arrayEnumerate(t.1), t.1, t.2) as idx
FROM __ip_block_to_asn
);
我遇到以下异常:
Received exception from server (version 1.1.54394):
Code: 241. DB::Exception: Received from localhost:9000, ::1. DB::Exception: Memory limit (for query) exceeded: would use 512.02 GiB (attempt to allocate chunk of 549755813888 bytes), maximum: 37.25 GiB.
我的问题是:
SELECT groupArray(min_ip),groupArray(max_ip),groupArray(country_iso_code),groupArray(country_name)
与__ip_block_to_asn
的每条记录一起执行,因此查询需要这么多的内存。这对我的查询是否正确?答案 0 :(得分:3)
标量子查询仅执行一次。
但是要执行arrayFilter
,将数组乘以__ip_block_to_asn
表中已处理块的行数。就像两个表的交叉连接一样。
要解决此问题,可以对__ip_block_to_asn
中的SELECT使用较小的块大小。
它由max_block_size
设置控制。但是对于Memory
表,无论SELECT期间的max_block_size
设置如何,块总是具有与插入表时相同的大小。要允许灵活的块大小,可以将该表重新加载到TinyLog
引擎中。
CREATE TABLE __ip_block_to_asn2 ENGINE = TinyLog AS SELECT * FROM __ip_block_to_asn
然后执行:
SET max_block_size = 10;
SELECT idx from(
SELECT
(
SELECT groupArray(min_ip),groupArray(max_ip),groupArray(country_iso_code),groupArray(country_name)
FROM __ip_block_to_country
) t,
arrayFilter((i,mii, mai) -> min_ip >= mii and max_ip <= mai, arrayEnumerate(t.1), t.1, t.2) as idx
FROM __ip_block_to_asn2
);