V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  yjhatfdu2  ›  全部回复第 1 页 / 共 4 页
回复总数  69
1  2  3  4  
find . -name '*.csv.gz' | xargs -I {} -P 4 bash -c "gzcat {} | psql -c 'copy test from stdin csv header'"
P 是并发,可以开高点
16 天前
回复了 zdking08135 创建的主题 程序员 请教一个系统设计题
@zdking08135 当然可以,不过按照这个编码形式,肯定要指定 country
17 天前
回复了 zdking08135 创建的主题 程序员 请教一个系统设计题
clickhouse 造一天数据试试看,单机 64 核 epyc 256G ram
建表,目前试下来效率最高的表结构
create table test4
(
time datetime CODEC (DoubleDelta, LZ4),
country UInt8 CODEC (DoubleDelta, LZ4),
province UInt8 CODEC (DoubleDelta, LZ4),
city UInt16 CODEC (DoubleDelta, LZ4),
uid UInt32
) engine = MergeTree() partition by toYYYYMMDD(time)
order by (time, country, province, city) settings index_granularity = 65536;

先造 10 亿数据,分布在一天内
insert into test4
select dateAdd(second, number / 1000000000, toDateTime('2024-04-02'))
, rand32() % 200
, rand32(1) % 250
, rand32(2) % 100
, number + 1
from numbers(1000000000);
-- 然后扩增到 32 倍
insert into test4 select * from test4;
insert into test4 select * from test4;
insert into test4 select * from test4;
insert into test4 select * from test4;
insert into test4 select * from test4;

SELECT count(*)
FROM test4

Query id: a4a01197-a22b-4a0d-9747-26555229ff58

┌─────count()─┐
│ 32000000000 │
└─────────────┘

1 row in set. Elapsed: 0.004 sec.
一共 320 亿
等后台 merge 完才 14.28 GiB 磁盘占用
楼主要的查询
WITH r AS
(
SELECT count() AS c
FROM test4
WHERE country = 100
GROUP BY uid
)
SELECT avg(c)
FROM r

Query id: c634e7a7-13fa-4d40-9f30-e6e43105ffe9

┌─avg(c)─┐
│ 32 │
└────────┘

1 row in set. Elapsed: 0.168 sec. Processed 160.30 million rows, 801.18 MB (954.12 million rows/s., 4.77 GB/s.)
0.168 秒完成

这样看起来,一年的数据单机也问题不大
注意,不同的建表语句尤其是 CODEC 非常影响存储空间和性能
17 天前
回复了 zdking08135 创建的主题 程序员 请教一个系统设计题
这个量,clickhouse 集群,做好表的设计,选好排序键、字段编码和压缩,按天分区,这个量写入和查询问题应该都不是很大。顺便,兄弟你这是在做天网么
@woodytang pg 下,如果可以用程序生成返回列然后拼接 SQL ,那么很简单
//创建测试表
create table test3("user" text,amount int,datetime timestamp);
insert into public.test3 (user, amount, datetime)
values ('A', 10, '2021-02-12 10:00:00.000000'),
('A', 20, '2021-03-12 10:00:00.000000'),
('B', 30, '2021-05-12 10:00:00.000000'),
('B', 10, '2021-06-12 10:00:00.000000'),
('C', 10, '2021-06-12 10:00:00.000000'),
('C', 20, '2021-06-12 10:00:00.000000'),
('C', 5, '2021-05-12 10:00:00.000000');
//使用 crosstab 进行 pivot
select *
from crosstab($$select "user",date_trunc('month',datetime)::date::text,sum(amount)
from test3 group by 1,2 order by 1,2 $$,
'select distinct date_trunc(''month'',datetime)::date::text from test3 order by 1') as ct(
"user" text,
"2021-02" text,
"2021-03" text,
"2021-05" text,
"2021-06" text
);
//结果
user | 2021-02 | 2021-03 | 2021-05 | 2021-06
------+---------+---------+---------+---------
A | 10 | 20 | |
B | | | 30 | 10
C | | | 5 | 30

如果要动态生成返回列名,那么确实是相当的麻烦,因为 pg 的查询必须显式制定列,只能用非常别扭的方式
-- 创建一个函数,实际查询的 SQL ,可以反复使用
create or replace function crosstabquery(_t anyelement) returns setof anyelement as
$$
declare
column_list text;
begin
select string_agg(format('%I text', d), ',')
into column_list
from (select distinct date_trunc('month', datetime)::date::text d from test3 order by 1) r;
return query execute ($b$select *
from crosstab($a$select "user",date_trunc('month',datetime)::date::text,sum(amount)
from test3 group by 1,2 order by 1,2 $a$,
'select distinct date_trunc(''month'',datetime)::date::text from test3 order by 1') as ct("user" text,$b$ ||
column_list||')' );
end ;
$$
language plpgsql;
-- 创建返回类型,每次使用前调用
do
$$
declare
column_list text;
begin
select string_agg(format('%I text', d), ',')
into column_list
from (select distinct date_trunc('month', datetime)::date::text d from test3 order by 1) r;
drop type if exists __t;
execute format('create type __t as ("user" text, %s)', column_list);
end
$$ language plpgsql;
-- 返回实际结果
select * from crosstabquery(null::__t);
user | 2021-02-01 | 2021-03-01 | 2021-05-01 | 2021-06-01
------+------------+------------+------------+------------
A | 10 | 20 | |
B | | | 30 | 10
C | | | 5 | 30
(3 rows)

不过如果可以动态生成 sql ,就别用下面这个方案,实在是别扭
这不是一句 sql 查询就能解决的事情吗,为啥要变复杂?
28 天前
回复了 xyxy 创建的主题 数据库 海量数据存储问题,求大佬们指导选型
你这量,只要不是要求一次几亿的数据聚合秒级结果,直接 pg+时间列 brin 索引解决了,然后老数据定期归档
云场景、实时性要求不高的场景有成本和灵活性优势,非云场景或者实时性要求高的场景就不适合了
补一个 window 的,i510 代标压 edge ,12 分
@zzxqd 主要影响的是加载时间和复杂 webapp 的响应速度,同时反过来也会影响能效,顺便,现在兼容性最差和功能缺失的可不一定是 webkit ,https://web.dev/blog/interop-2023
@zzxqd 看一下刚更新的 speedometer3.0 ,已经更加贴近各种实际场景了,也是 G 、M 等共同参与的 https://webkit.org/blog/15131/speedometer-3-0-the-best-way-yet-to-measure-browser-performance/
@yjhatfdu2 更正:50 米内点的数量
@249239432 我单机 pg 查了 1000w 个点,每个点附近 50 个点的数量(平均 5 个左右)也就 20 分钟
explain analyse select id,(select count(*) from geo where st_dwithin(point,g.point,50)) from geo g;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------
Seq Scan on geo g (cost=0.00..165365708334.00 rows=10000000 width=12) (actual time=1.076..1049434.731 rows=10000000 loops=1)
SubPlan 1
-> Aggregate (cost=16536.54..16536.55 rows=1 width=8) (actual time=0.105..0.105 rows=1 loops=10000000)
-> Index Scan using geo_point_idx on geo (cost=0.54..16534.04 rows=1000 width=0) (actual time=0.027..0.104 rows=14 loops=10000000)
Index Cond: (point && _st_expand(g.point, '50'::double precision))
Filter: st_dwithin(point, g.point, '50'::double precision, true)
Rows Removed by Filter: 7
Planning Time: 0.756 ms
Execution Time: 1049626.246 ms
(9 rows)

Time: 1049627.962 ms (17:29.628)
@249239432 计算次数和算法是很有关的,比如你要圈每一个点附近 50 米的所有点,你可以两次 for 循环每两个之间算一次,也可以排序/索引之后,每个点只需要用 LogN 次查询
38 天前
回复了 avadakur 创建的主题 程序员 关于数据库高并发插入的版本号问题
@shinelamla 你这样的问题也是高并发下,失败概率会很高
38 天前
回复了 avadakur 创建的主题 程序员 关于数据库高并发插入的版本号问题
如果是 pg 的话,可以考虑用 advisory_lock,读之前针对 user_id 的值加锁,更新完解锁,这样不会对表或者行加高级的锁,避免影响其他业务,也可以避免引入 redis 带来的通讯开销,应该是性能非常高的方案了
38 天前
回复了 avadakur 创建的主题 程序员 关于数据库高并发插入的版本号问题
@shinelamla 这个是个典型的不可重复读问题,在 RR 的隔离等级下,这种情况不被允许,一般来说,后一个提交的事务会失败,以避免数据不一致
38 天前
回复了 avadakur 创建的主题 程序员 关于数据库高并发插入的版本号问题
如果不是必须先获取当前 version 做业务操作然后再更新,那么直接 update version set version=version+1 where xxxx 就可以了,如果必须先获取 version 再做一些业务操作再更新,就得开事务了,然后高并发的情况还得考虑事务失败概率高的问题,可以根据你的数据库实际情况考虑使用显式锁来减少事务冲突导致的失败
38 天前
回复了 avadakur 创建的主题 程序员 关于数据库高并发插入的版本号问题
开事务
@249239432 你估计没排序吧,你这算法复杂度有点高排个序应该就是 ONLogN 了
1  2  3  4  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1192 人在线   最高记录 6543   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 120ms · UTC 23:51 · PVG 07:51 · LAX 16:51 · JFK 19:51
Developed with CodeLauncher
♥ Do have faith in what you're doing.