场景:通过借助从hive查询全量数据缩短原先从es中查询全量数据所耗费的时间
第一步:
将es中数据全量同步到内部表in_table中,通过hive调用查询语句可查询到全量数据,同步过程可见上一篇博客:
Hive环境搭建+读取es数据到内部表_Jibo12138的博客-CSDN博客
通过在hive调用查询语句查询数据总量,本场景下的数据总量达到89004250条
第二步:
编写spark sql代码,通过spark查询es中某索引的全量数据:
public static void main(String[] args){
SparkSession spark=SparkSession.builder().master("local[3]").appName("测试es").getOrCreate();
SparkUdfRegister.register(spark);
Map<String,String> esConfig=new HashMap<>(10);
esConfig.put(ConfigurationOptions.ES_NODES,"es地址");
esConfig.put(ConfigurationOptions.ES_NODES_WAN_ONLY,"true");
esConfig.put(ConfigurationOptions.ES_PORT,"es端口");
esConfig.put(ConfigurationOptions.ES_NET_HTTP_AUTH_USER,"es用户名");
esConfig.put(ConfigurationOptions.ES_NET_HTTP_AUTH_PASS,"es密码");
esConfig.put(ConfigurationOptions.ES_RESOURCE,"es索引");
spark.read().format("org.elasticsearch.spark.sql").options(esConfig).load().createOrReplaceTempView("source_table_es");
spark.sql("select * from source_table_es").count();
}
打jar包之后,把jar包拖到linux上,执行命令:
./spark-submit --class 主类路径 --master local[3] jar包路径
最终读取全量数据完毕
第三步:
编写spark sql代码,通过spark查询hive内部表中存储的与es中同样的全量数据
public static void main(String[] args){
SparkSession spark=SparkSession.builder().master("local[2]").appName("query hive").config("spark.sql.warehouse.dir","hdfs://warehouse的路径,如何配置可见上一篇文章").config("hive.metastore.uris","thrift://metastore地址加端口").enableHiveSupport().getOrCreate();
spark.sql("select * from in_table").count();
}
hive需要开启metastore服务,可以在hive的bin目录下执行命令:
./hive --service metastore -p 9083 &
也可以在hive-site.xml里增加hive.metastore.uris配置项:
<property>
<name>hive.metastore.uris</name>
<value>thrift://服务器ip:端口</value>
</property>
同样,打jar包放入服务器中执行,最终查询全量数据只需要33s。
但是es查询时间较长的原因主要是需要拉远程数据到本地来(说不定本地内存小的,拉过来的数据还没等处理就因为没内存而报错了),而hive执行期间最耗时的是在数据处理的过程。如果sql语句为:
select count(ip) from in_table group by port order by count(ip) dec;
es经过查询之后,本地再把es的数据拉过来,此时数据量较少,就极有可能出现查询es的时间小于hive的情况
综上,不一定hive查询效率一定比es高,具体如何使用,还是要根据实际情况来定。如果所做的业务场景中所用的条件查询或者聚合比较多,就需要做一下hive和es查询,两种方案的预研工作。