Es与MongoDB地理数据搜索性能比较

Es与MongoDB地理数据搜索性能比较

基础环境信息

主机信息:

  • 处理器:i5-9400 2.90GHz
  • 内存:16G
  • 硬盘:224G

软件信息:
Es:

  • 版本:7.6.2
  • JDK 1.8
  • 单机模式运行
  • 默认配置文件

Es客户端:

  • RestHighLevelClient 7.6.2

Mongo:

  • 版本:4.2.11
  • 单机模式运行
  • 默认配置文件

Mongo客户端:

  • spring-data-mongodb 3.1.2
  • mongodb-driver-sync 4.1.1

准备和录入测试数据

分别在Es和MongoDB中和存储10、100w等数量的坐标点数据,并随机在其中插入若干数量的测试坐标点,作为范围查询的记录。以下分别是es和mongo对应的数据说明。数据格式采用标准地理数据格式,但在两个数据库中格式略有不同,数据格式标准为RFC7946

Es存储数据

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [125.6, 10.1]
  },
  "properties": {
    "name": "Dinagat Islands"
  }
}

es中geo格式的数据:

  • geo_point
    地理坐标点,在Elasticsearch中用来存经纬度数据的一种数据格式。在es中指定数据类型:
{
  "mappings": {
     "store":{
      "properties": {
          "location":{
            "type": "geo_point"
          }
      }
     }
  }
}

存储示例:

{
"_index": "my-index-geo-01",
"_type": "_doc",
"_id": "100",
"_version": 1,
"_score": 1,
"_source": {
"location": "-9.85,-28.76"
}
}

Mongo存储数据

坐标数据格式,mongo支持两个格式:
格式一,为mongo支持的较标准的地理格式,但是与geoJson略有不同;支持2d和2dsphere索引:

{
        "_id" : 0,
        "loc" : {
                "coordinates" : [
                        21.38,
                        -40.7
                ],
                "type" : "Point"
        }
}

格式二,较旧的格式模式,支持2d和2dsphere索引:

{ "_id" : 0, "loc" : [ 3.78, 5.94 ] }

创建集合和坐标索引:

db.demo.createIndex({loc: "2dsphere" })

查询耗时比较

查询数据方式

ES:按照geo_distance方式查询,找出指定位置在给定距离内的数据,相当于指定圆心和半径找到圆中点。
Mongo:支持较多的查询方式,分别为圆形查询(球体)、圆形查询和球面直线查询。

不同客户端端查询耗时比较

客户端查询耗时/ms10w20w30w40w50w60w100w
ES(RestHighLevelClient)153150139139142144141
MongoDB(MongoTemplate,圆形查询(球体))91949496919591
MongoDB(Mongo cilent,圆形查询(球体))60636665656367

说明:
查询的数据集均创建过对应索引。

不同查询方式比较

MongoDB中提供了对于圆形区域提供了不同方式的查询,以下是查询相同数据集的结果比较:

MongoDB不同查询方式耗时/ms10w100w
MongoDB(MongoTemplate,圆形查询(球体))8991
MongoDB(MongoTemplate,圆形查询)9190
MongoDB(Mongo cilent,圆形查询(球体))6067
MongoDB(Mongo cilent,圆形查询)6264

说明:
不同的查询方式需创建不同的索引,不然查询时间较长。
球面直线查询误差较大,查询结果中出现了许多不准确的坐标点,故不在对比结果中。
上面查询的耗时的前提是创建了对应格式的索引。

有无索引查询比较

下面给出有无创建索引的查询耗时比较结果:

MongoDB查询耗时/ms50w100w
MongoDB(MongoTemplate,圆形查询(球体)),创建索引9187
MongoDB(MongoTemplate,圆形查询(球体)),未创建索引7091358
MongoDB(Mongo cilent,圆形查询(球体)),创建索引6367
MongoDB(Mongo cilent,圆形查询(球体)),未创建索引6681310

结论:
在相同地理数据集的情况下,mongo数据库的查询耗时比es数据库短大约30~40%。
spring data mongo提供了基于mongo driver的一层封装,使用起来更加简单便捷,如提供了序列化和反序列化的处理。原生的mongo client也提供了全面的查询方法,查询效率略高一些,不过在程序中需要增加一些处理代码,如序列化方法等,仅对结果简单处理时可以考虑使用。
有无创建索引,对于地理数据的查询耗时影响较大。

客户端查询耗时分析

通过查看MongoTemplate源码,template是在client的基础上做了封装,为了保证了读写数据的安全和于查询结果的处理更加简单,添加了包括对查询结果的映射,包括嵌套数据;上锁保证线程安全等处理代码。添加的处理逻辑增加了一部分时间开销。如下是template查询时的核心代码块:

private <T> List<T> executeFindMultiInternal(CollectionCallback<FindIterable<Document>> collectionCallback,
			CursorPreparer preparer, DocumentCallback<T> objectCallback, String collectionName) {

		try {

			MongoCursor<Document> cursor = null;

			try {

				cursor = preparer
						.initiateFind(getAndPrepareCollection(doGetDatabase(), collectionName), collectionCallback::doInCollection)
						.iterator();//获取查询的原始结果

				List<T> result = new ArrayList<>();

				while (cursor.hasNext()) {
					Document object = cursor.next();
					result.add(objectCallback.doWith(object));//处理原始数据,映射成对应的数据类型
				}

				return result;
			} finally {

				if (cursor != null) {
					cursor.close();
				}
			}
		} catch (RuntimeException e) {
			throw potentiallyConvertRuntimeException(e, exceptionTranslator);
		}
	}

地理空间数据模型说明

数据类型

mongo中支持的地理空间数据类型有:Point、LineString、Polygon、MultiPoint、MultiLineString、MultiPolygon、GeometryCollection。
坐标点的数据结构是:

{ type: "Point", coordinates: [ 40, 5 ] }

空间数据索引

2dsphere索引:支持球面空间查询。
2d索引:支持平面空间查询,支持部分球面查询,但是会出现误差。推荐尽量使用2dsphere索引。

查询方式

主要有四种查询类型、计算方法说明及索引支持:

名称说明索引支持
$near查询指定一个点在平面中从最近到最远的坐标点。2dsphere and 2d
$nearSphere查询指定一个点在球面中从最近到最远的坐标点。2dsphere and 2d
$geoWithin查询指定多边形形状中全部的坐标点。包括的形状有:矩形、多边形、圆形和球面圆形。2dsphere and 2d
$geoIntersects查询与指定GeoJSON对象相交的坐标点。2dsphere

从10w个数据点中查询某个坐标点相近的坐标点的结果,实际数据中有五个参考点:

名称查询结果数量
$near(直线距离最远1m内)14
$nearSphere(直线距离最远1m内)31356
$geoWithin(半径在1m的平面圆形内)5
$geoWithin(半径在1m的球面圆形内)5
$geoIntersects(与参考点相交的点)5
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值