ElasticSearch第4篇(亿级中文数据量 ElasticSearch与Sphinx建索引速度、查询速度、并发性能、实测对比)

经过实测:1.09亿的数据量进行中文检索。ElasticSearch单机的检索性能在0.005~5.6秒之间,此检索速度可满足95%的业务场景(注意:每条ES文档平均65个汉字,数据源取自几千本小说,大部分文档在15~300个汉字之间,不然字数太多索引太大电脑存不下)。

前置文章

由于本文章的前置操作强依赖于另一篇文章,推荐阅读:
万字详解PHP+Sphinx中文亿级数据全文检索实战(实测亿级数据0.1秒搜索耗时)

运行配置

和Sphinx环境保持一致。
服务器配置:CentOS7.6 16核4G内存。固态硬盘。
ES配置:ElasticSearch 8.14.1单机,默认配置,使用IK分词器的ik_max_word配置。不设置分片和副本数量。

数据准备

和Sphinx用的数据源保持一致。
依旧是上次用的几千本小说,整合后的单个txt文件9.57个G,用\n间隔,作为一个ES文档。
数据量为109 450 000条数据。

数据插入

  • 创建索引与映射,并修改max_result_window参数
$params = [
    'index' => 'performance_test',
    'body'  => [
        'settings' => [
            'analysis' => [
                'analyzer' => [
                    'ik_analyzer' => [
                        'type'      => 'ik_max_word',
                    ],
                ],
            ],
        ],
        'mappings' => [
            'properties' => [
                'id' => [
                    'type'     => 'integer',
                ],
                'content' => [
                    'type'     => 'text',
                    'analyzer' => 'ik_analyzer',
                ],
            ],
        ],
    ],
];

$response = $client->indices()->create($params);
dd($response->asBool());


$params = [
    'index' => 'performance_test',
    'body'  => [
        'index' => [
            'max_result_window' => 2147483647 //用于控制在搜索查询中可以检索到的最大文档数,有符号int类型,最大可设置2^31 - 1,大了会有性能问题
        ]
    ]
];

$response = $client->indices()->putSettings($params);
dd($response->asBool());
  • 插入数据
//这段代码只确保可批量插入,忽略精准的数据处理高可用问题。
$start = microtime(true);
ini_set('memory_limit', '4096M');
set_time_limit(0);

include __DIR__ . './vendor/autoload.php';

$client = \Elasticsearch\ClientBuilder::create()->setHosts(['192.168.0.183:9200'])
    ->setBasicAuthentication('elastic', '123456')->build();


/**
 * @function 逐行读取大文件
 * @param    $file_name string 文件名
 * @return   Generator|object
 */
function readLargeFile($file_name) {
    $file = fopen($file_name, 'rb');
    if (! $file) {
        return false;
    }

    while (! feof($file)) {
        $line = fgets($file);
        if ($line !== false) {
            yield $line;
        }
    }

    fclose($file);
}


// 使用生成器逐行读取大文件
$file_resource = readLargeFile('E:/其它/一亿行汉字文本.txt');
foreach ($file_resource as $loop => $line) {
    $loop ++;
    $from_charset = mb_detect_encoding($line, 'UTF-8, GBK, GB2312, BIG5, CP936, ASCII');
    $utf8_str     = @iconv($from_charset, 'UTF-8', $line);
    if(in_array($utf8_str, ["\n", "\r", "\n\r", "\r\n"])) {
        continue;
    }


    $params['body'][] = ['index' => ['_index' => 'performance_test', '_id' => $loop]];
    $params['body'][] = ['id' => $loop, 'content' => $utf8_str];


    if(count($params['body']) >= 100000) {
        $client->bulk($params); //忽略批量插入的错误
        $params = [];
    }
}

echo '插入耗时:' . bcsub(microtime(true), $start, 3) . '秒';

实测ES与Sphinx新增数据建索引速度对比

应用 耗时 新增数据量 补充
Sphinx 50.5分钟 109 450 000 /
ElasticSearch 119分钟 109 450 000 (总时间 - PHP代码执行时间,总耗时190分钟)

实测ES与Sphinx查询性能对比

某些项,ElasticSearch搜索出来的结果远超MySQL和Sphinx查询的结果,这是分词汇总的缘故。
而Sphinx使用的是SPH_MATCH_PHRASE格式,所以数量不会有ES那么多,若用SPH_MATCH_ANY,可能有更多的检索结果。

类型 搜索关键字 Sphinx搜索耗时(秒) ES搜索耗时(秒) MySQL搜索耗时(秒) Sphinx搜索数量 ES搜索数量 MySQL搜索数量
数字 123 0.005 0.005 305.142 3121 3877 8143
中文单字 0.013 0.115 223.184 67802 60016 103272
英文单字母 A 0.031 0.009 339.576 136428 0 1017983
单中文标点 4.471 0.003 125.106 67088012 0 67096182
单英文标点 . 0 0.003 251.171 0 0 6697242
可打印特殊字符 0 0.002 355.469 0 0 0
中文词语(易分词) 黑色衣服 0.066 0.283 346.442 1039 722402 1062
中文词语(不易分词) 夏威夷 0.011 0.114 127.054 3636 3664 3664
中文词语(热门) 你好 0.022 0.091 126.979 102826 136996 137717
中文词语(冷门) 旖旎 0.010 0.077 345.493 4452 4496 4528
英文单词 good 0.010 0.074 137.562 553 588 1036
中文短语 他不禁一脸茫然 1.742 0.973 218.272 0 49698660 0
英文短语 I am very happy 0.015 0.121 355.235 1 48375 0
长文本 陈大人不急着回答,他先从柜台下面又抽出了一份文案,翻了好一阵之后才回答道:“瞧,果然如此,如今广州这边官职该放得都放出去了,只剩下消防营山字营的一个哨官之职。不出所料的话,督抚大人准会委你这个职务。 0.131 5.638 129.204 1 80498922 1

实测ES与Sphinx并发性能对比

  • 压测方式 :ab -c 1 -n 10~1000 127.0.0.1/temp/es/test.php
  • 中文定值关键字为华盛顿,英文定值关键字为XYZ,30位随机中文或英文字符,由代码生成(用代码生成数据源,是避免引入更好的数据源带来了性能误差)。
  • 由于ES IK分词器比Sphinx中文分词器分词粒度更细,所以并发下30位随机中文字符检索性能极具下降。
生成任意正整数个中文字符
function generateRandomChinese($length) {
    $result = '';
    for ($i = 0; $i < $length; $i++) {
        $result .= mb_convert_encoding('&#' . mt_rand(0x3e00, 0x9fa5) . ';', 'UTF-8', 'HTML-ENTITIES');
    }
    return $result;
}

生成任意正整数个英文字符
function generateRandomEnglish($length) {
    $result = '';
    for ($i = 0; $i < $length; $i++) {
        $result .= chr(mt_rand(97, 122)); // 小写字母ASCII码范围: 97~122;大写字母:65~90
    }
    return $result;
}
类型 搜索次数(ab -n 参数值) Sphinx耗时(秒) ES耗时(秒)
固定中文多次搜索 10 0.256 0.623
固定中文多次搜索 100 1.435 1.915
固定中文多次搜索 1000 11.604 18.821
随机30位中文字符多次搜索 10 0.517 4.257
随机30位中文字符多次搜索 100 2.305 52.505
随机30位中文字符多次搜索 1000 17.197 超时
固定英文多次搜索 10 0.327 0.584 0.584
固定英文多次搜索 100 0.747 5.085
固定英文多次搜索 1000 8.510 50.423
随机30位英文字符多次搜索 10 0.077 0.0623
随机30位英文字符多次搜索 100 0.766 4.810
随机30位英文字符多次搜索 1000 9.428 50.698

ES与Sphinx各项优缺点直观对比

项目 ElasticSearch(相比于Sphinx) Sphinx(相比于ElasticSearch)
创建索引性能
查询性能 相差无几 相差无几
并发性能
中文分词支持 需安装IK分词器 需安装Mmseg分词工具和Coreseek中文搜索引擎框架
实时搜索 友好 不友好
对增量数据(Insert) 通过代码层可直接同步ES 需要运维层面的触发而生成增量索引
与数据库一致性同步问题(Update、Delete) ES支持直接更新 Sphinx不支持对索引更新,需重建索引
客户端语言支持 Java、PHP、JavaScript、Perl、Ruby、Python、Golang、Eland、.NET、Rust Java、PHP、Python、Perl、C
开发语言 Java C++
支持跨平台
架构 C/S C/S
合作流程 内置数据库,支持对自身数据进行复杂的增删改查,但需要MySQL兜底 内置索引库、帮MySQL找ID
事务支持 不支持 不支持
系统内存占用
集群部署 支持 支持
集群协调模式 自动负载均衡 节点间协调 需要手动设置负载均衡和协调
数据分析 内建强大的聚合和分析功能 不支持复杂的数据分析
GUI 需额外安装组件,例如Kibana 无官方可视化工具
生态 繁荣 一般
上手难度
安全性 支持基于用户的访问控制,集成X-Pack进行高级安全配置。但内部的Log4j2组件存在高危漏洞 基本的权限管理,需依赖外部工具
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,451评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,172评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,782评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,709评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,733评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,578评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,320评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,241评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,686评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,878评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,992评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,715评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,336评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,912评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,040评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,173评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,947评论 2 355

推荐阅读更多精彩内容