从Oracle导入数据到ElasticSearch

使用工具是logstash6.2.4

https://www.elastic.co/cn/

首先要知道的是,logstash抽取Oracle的数据是通过追踪某一个递增列实现增量导入的,所以就要求在查询结果有一个递增列,这并不是说需要一个自动增长列,因为在Oracle中,rownum可以作为查询结果中的一个递增列,如

SELECT * FROM(SELECT NP.*, ROWNUM RN FROM (SELECT * FROM NPMIS_ZW_YSDFMX) NP ) WHERE RN BETWEEN 5000001 AND 6000000;

所以logstash可以追踪rownum来增量导入。

有自动增长列

orderid为自动增长列

input {

jdbc {

jdbc_driver_library => "/opt/app/logstash-6.2.4/orcl-lib/ojdbc6.jar"

jdbc_driver_class => "Java::oracle.jdbc.driver.OracleDriver"

jdbc_connection_string => "jdbc:oracle:thin:@10.10.10.13:1521:testdb11g"

jdbc_user => "udvmp"

jdbc_password => "pwdvmp"

schedule => "*/2 * * * *"

statement => "SELECT * FROM NPMIS_ZW_YSDFMX_BAK_BAK WHERE orderid > :sql_last_value"

record_last_run => "true"

use_column_value => "true"

tracking_column => "orderid"

last_run_metadata_path => "/opt/app/logstash-6.2.4/config/last_id"

clean_run => "false"

}

}

filter {

mutate {

convert => { "zdl" => "float_eu"}

}

}

output {

elasticsearch {

hosts => "cdh05.codsway.com"

index => "obak-npmis_zw_ysdfmx_bak"

document_id => "%{orderid}"

}

}

没有自动增长列

把rownum查询出来作为一列,rn模拟自动增长列

input {

jdbc {

jdbc_driver_library => "/opt/app/logstash-6.2.4/orcl-lib/ojdbc6.jar"

jdbc_driver_class => "Java::oracle.jdbc.driver.OracleDriver"

jdbc_connection_string => "jdbc:oracle:thin:@10.10.10.13:1521:testdb11g"

jdbc_user => "udvmp"

jdbc_password => "pwdvmp"

schedule => "*/2 * * * *"

statement => "SELECT * FROM(SELECT NP.*, ROWNUM RN FROM (SELECT * FROM NPMIS_ZW_YSDFMX_BAK) NP) WHERE RN > :sql_last_val

ue"

record_last_run => "true"

use_column_value => "true"

tracking_column => "rn"

last_run_metadata_path => "/opt/app/logstash-6.2.4/config/last_id"

clean_run => "false"

}

}

filter {

mutate {

convert => { "zdl" => "float_eu"}

}

}

output {

elasticsearch {

hosts => "cdh03.codsway.com"

index => "orcl-npmis_zw_ysdfmx_bak"

document_id => "%{rn}"

}

}

数据重复问题和Oracle增量数据ES同步慢问题

在默认配置下,tracking_column这个值是@timestamp,存在elasticsearch就是_id值,是logstash存入elasticsearch的时间,这个值的主要作用类似mysql的主键,是唯一的,但是我们的时间戳其实是一直在变的,所以我们每次使用select语句查询的数据都会存入elasticsearch中,导致数据重复。

解决方法:在要查询的表中,找主键或者自增值的字段,将它设置为_id的值,因为_id值是唯一的,所以,当有重复的_id的时候,数据就不会重复

input

// 是否记录上次执行结果, 如果为真,将会把上次执行到的 tracking_column 字段的值记录下来,保存到 last_run_metadata_path 指定的文件中

record_last_run => "true"

// 是否需要记录某个column 的值,如果record_last_run为真,可以自定义我们需要 track 的 column 名称,此时该参数就要为 true. 否则默认 track 的是 timestamp 的值.

use_column_value => "true"

// 如果 use_column_value 为真,需配置此参数. track 的数据库 column 名,该 column 必须是递增的. 一般是mysql主键,由于我们是用rownum也是递增的,可以在sql语句中查询出rownum作为这一列,orderid是rownum别名

tracking_column => "orderid "

last_run_metadata_path => "/opt/app/logstash-6.2.4/config/last_id"

//如果不设置,会从头开始再查询一次,因为数据量巨大所以导致同步的时间会很长,可能导致Oracle数据没有同步到ES

clean_run => "false"

//sql语句最后添加WHERE orderid > :sql_last_value,如果不适用where,那么之前的所有配置同步的配置都没有生效,每次都执行查询全部的语句,然后在大量的结果集中比较orderid,再将符合要求的数据插入ES,所以非常耗时间,:sql_last_value会读取last_run文件的值,如果没有这个文件就赋值为0开始

statement => "SELECT np.*,ROWNUM orderid FROM NPMIS_ZW_YSDFMX_BAK_BAK np WHERE orderid > :sql_last_value"

output

//index必须固定,不能随时间增长

index => "ORCL-NPMIS_ZW_YSDFMX_BAK"

//把查询出来的rownum赋值给document_id,document_id在文档中具有唯一性,所以不会重复,也就不会插入重复数据

document_id => "%{orderid }"

实际上并不是不同步,而是没有记录上次Oracle查询的位置,所以保存上次的查询记录就行了

数据丢失问题

logstash读取数据类型是由第一行或前几行决定的,所以如果某一列第一行值是整数,那么logstash就认定这一列是整数,第二行是小数,可能会把小数强转成整数,然后因为出现error丢失第二行或多行,丢失行可以在日志文件中看到,所以我们需要设置filter对列类型进行转换。

通过查看日志文件,查看出问题的是第几列,然后强转该列的类型。

float_eu是因为oracle查询出来的数据带有,号分隔符,比如12,340.99,所以需要写成float_eu,写成float会报错。如果是其他数据库可以试试float

filter {

mutate {

convert => { "zdl" => "float_eu"}

}

}

猜你喜欢

转载自blog.csdn.net/chroje/article/details/80412967
今日推荐