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新增数据建索引速度对比

应用耗时新增数据量补充
Sphinx50.5分钟109 450 000/
ElasticSearch119分钟109 450 000(总时间 - PHP代码执行时间,总耗时190分钟)

实测ES与Sphinx查询性能对比

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

类型搜索关键字Sphinx搜索耗时(秒)ES搜索耗时(秒)MySQL搜索耗时(秒)Sphinx搜索数量ES搜索数量MySQL搜索数量
数字1230.0050.005305.142312138778143
中文单字0.0130.115223.1846780260016103272
英文单字母A0.0310.009339.57613642801017983
单中文标点4.4710.003125.10667088012067096182
单英文标点.00.003251.171006697242
可打印特殊字符00.002355.469000
中文词语(易分词)黑色衣服0.0660.283346.44210397224021062
中文词语(不易分词)夏威夷0.0110.114127.054363636643664
中文词语(热门)你好0.0220.091126.979102826136996137717
中文词语(冷门)旖旎0.0100.077345.493445244964528
英文单词good0.0100.074137.5625535881036
中文短语他不禁一脸茫然1.7420.973218.2720496986600
英文短语I am very happy0.0150.121355.2351483750
长文本陈大人不急着回答,他先从柜台下面又抽出了一份文案,翻了好一阵之后才回答道:“瞧,果然如此,如今广州这边官职该放得都放出去了,只剩下消防营山字营的一个哨官之职。不出所料的话,督抚大人准会委你这个职务。0.1315.638129.2041804989221

实测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耗时(秒)
固定中文多次搜索100.2560.623
固定中文多次搜索1001.4351.915
固定中文多次搜索100011.60418.821
随机30位中文字符多次搜索100.5174.257
随机30位中文字符多次搜索1002.30552.505
随机30位中文字符多次搜索100017.197超时
固定英文多次搜索100.3270.584
固定英文多次搜索1000.7475.085
固定英文多次搜索10008.51050.423
随机30位英文字符多次搜索100.0770.0623
随机30位英文字符多次搜索1000.7664.810
随机30位英文字符多次搜索10009.42850.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、RustJava、PHP、Python、Perl、C
开发语言JavaC++
支持跨平台
架构C/SC/S
合作流程内置数据库,支持对自身数据进行复杂的增删改查,但需要MySQL兜底内置索引库、帮MySQL找ID
事务支持不支持不支持
系统内存占用
集群部署支持支持
集群协调模式自动负载均衡节点间协调 需要手动设置负载均衡和协调
数据分析内建强大的聚合和分析功能不支持复杂的数据分析
GUI需额外安装组件,例如Kibana无官方可视化工具
生态繁荣一般
上手难度
安全性支持基于用户的访问控制,集成X-Pack进行高级安全配置。但内部的Log4j2组件存在高危漏洞基本的权限管理,需依赖外部工具
  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小松聊PHP进阶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值