V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tanszhe
V2EX  ›  数据库

[如何在 1s 内统计出 13 亿人口使用人数最多的十个姓名] 的答案

  •  
  •   tanszhe · 2021-01-25 16:03:54 +08:00 · 2173 次点击
    这是一个创建于 1396 天前的主题,其中的信息可能已经有所发展或是发生改变。

    使用的工具

    环境 笔记本的虚拟机内

    top - 16:01:06 up 2 days,  3:44,  1 user,  load average: 0.09, 0.38, 0.71
    Tasks: 117 total,   1 running, 116 sleeping,   0 stopped,   0 zombie
    %Cpu0  :  0.0 us,  1.4 sy,  0.0 ni, 98.6 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
    MiB Mem :   1970.9 total,    354.0 free,    861.4 used,    755.5 buff/cache
    MiB Swap:   2045.0 total,   2044.5 free,      0.5 used.    786.5 avail Mem
    

    结果

    MiWiFi-R4A-srv :) select count(),name from t10 group by name order by count() desc limit 10;
    
    SELECT
        count(),
        name
    FROM t10
    GROUP BY name
    ORDER BY count() DESC
    LIMIT 10
    
    Query id: 79b52b2e-8fd0-4321-b4d1-270d3800164b
    
    ┌─count()─┬─name─────────────────┐
    │   13856 │ 异邦                 │
    │   13850 │ 长江三峡水利枢纽工程 │
    │   13849 │ 龙旗                 │
    │   13842 │ 王揖唐               │
    │   13832 │ 用费                 │
    │   13830 │ 兴办                 │
    │   13820 │ 榨油                 │
    │   13814 │ 增值                 │
    │   13805 │ 宗谱                 │
    │   13803 │ 膏粱                 │
    └─────────┴──────────────────────┘
    
    10 rows in set. Elapsed: 23.574 sec. Processed 1.35 billion rows, 22.66 GB (57.35 million rows/s., 961.18 MB/s.)
    

    过程

    $f     = fopen(__DIR__ . '/../dict.txt.small.txt', 'r');
    $names = [];
    while ($str = fgets($f)) {
        $arr = explode(' ', trim($str));
        if (strlen($arr[0]) > 5) {
            $names[] = $arr[0];
        }
    }
    
    
    • 建表并将数据写入数据库
    $ck = new Client('tcp://192.168.23.129:9091', 'default', '123456', 'test1');
    
    
    $data['drop table']   = $ck->query('DROP TABLE IF EXISTS t10');
    $table                = [
        'CREATE TABLE t10 (',
        '`name` String',
        ') ENGINE = MergeTree() ORDER BY name SETTINGS index_granularity = 8192'
    ];
    $data['create table'] = $ck->query(implode("\n", $table));
    for ($nj = 0; $nj < 150; $nj++) {
        $ck->writeStart('t10', ['name']);
        for ($i = 0; $i < 1000; $i++) {
            $da = [];
            for ($j = 0; $j < 10000; $j++) {
                $da[] = [
                    'name'  => $names[mt_rand(1, 101048)],
                ];
            }
            $ck->writeBlock($da);
        }
        $ck->writeEnd();
        echo 'nj : ' . $nj . PHP_EOL;
    }
    

    本打算写 15 亿的,感觉没必要 中途暂停了 一共写入了 1352100000 条记录。

    估计服务器 cpu 核心 8 以上的应该能达到 1s 以内。

    8 条回复    2021-01-25 16:43:54 +08:00
    magua
        1
    magua  
       2021-01-25 16:05:13 +08:00
    好狠
    tanszhe
        2
    tanszhe  
    OP
       2021-01-25 16:07:30 +08:00
    @magua 虚拟机单核性能不行
    so1n
        3
    so1n  
       2021-01-25 16:14:40 +08:00
    clickhouse 真香
    anonyp
        4
    anonyp  
       2021-01-25 16:16:49 +08:00 via iPhone
    试下 summingmergetree 存储引擎看看,感觉这个会比较适合聚合的场景
    tanszhe
        5
    tanszhe  
    OP
       2021-01-25 16:18:42 +08:00
    @anonyp 聚合引擎肯定会快很多的,这个相当于是缓存好了的 直接拿结果
    Yelp
        6
    Yelp  
       2021-01-25 16:19:22 +08:00
    没进来就想到 ClickHouse 了
    anonyp
        7
    anonyp  
       2021-01-25 16:42:40 +08:00 via iPhone
    @tanszhe 是的,OLAP 场景下就非常适合用特定的存储引擎
    Leonard
        8
    Leonard  
       2021-01-25 16:43:54 +08:00   ❤️ 2
    我点进来只是想知道 13 亿人口使用人数最多的十个姓名是哪十个
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3142 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 00:18 · PVG 08:18 · LAX 16:18 · JFK 19:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.