Open cjuexuan opened 7 years ago
请问当超过半数时:
case false ⇒
if (row.isNullAt(i - midField)) {
stmt.setNull(i + 1, nullTypes(i - midField))
} else {
setters(i).apply(stmt, row, i, midField)
}
是否应该是
case false ⇒
if (row.isNullAt(i - midField)) {
stmt.setNull(i + 1, nullTypes(i - midField))
} else {
setters(i - midField).apply(stmt, row, i, midField)
}
@SOBIGUFO 不是的,你可以看下numFields在isUpdateMode下已经*2了,这个代码可以本地设置个断点看下
举个例子
INSERT INTO table
(a
, b
) VALUES (?, ?) ON DUPLICATE KEY UPDATE a
=?,b
=?;
//(1,2)
首先如果isUpdate -> 这里numFields = length * 2 = 4
需要填充的4个值分别是1,2,1,2 midField = 2
所以isUpdate的时候,midField = 2 offset在到length之前都是0,所以相当于直接走row.get(pos) 在走完一遍循环以后 触发到 i > midField i - midField相当于再走一次循环,相当于第一次的row.get(pos)
@cjuexuan 我明白你上面说的,但是setters的大小就是rddSchema.fields.length
,而setters(i)
中的i在超过半数的时候不减去midField的话是会越界的。
@SOBIGUFO getSetter 中Array.fill(2)了,setter在遇到updateMode的时候已经扩展了一倍了,你越界的代码看下
@cjuexuan 明白了,刚才没有注意到getSetter
中已经Array.fill(2)
,谢谢!
@SOBIGUFO :)
从csdn迁移过来的
spark 的save mode
spark 的saveMode在
org.apache.spark.sql.SaveMode
下,是一个枚举类,支持而实际业务开发中,我们可能更希望一些行级别的动作而非这种表级别的动作
新的mysqlSaveMode
总结业务开发过程中常见的需求,设计出以下枚举类:
对应的执行SQL语句应该是
JDBCUtil 类的解读和满足需求下的重写
2.0之前的
org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils
其实是有问题的,对于每一行row的set都进行了比较类型,时间复杂度非常高,2.0之后重写出了一个setter逻辑,形成了一个prepareStatment的模板,这样瞬间将原来的比较类型进行了指数级优化,核心代码:这个虽然已经解决了大多数问题,但如果使用DUPLICATE还是有问题的:
insert into table_name (name,age,id) values (?,?,?)
insert into table_name (name,age,id) values (?,?,?) on duplicate key update name =? ,age=?,id=?
所以在prepareStatment中的占位符应该是row的两倍,而且应该是类似这样的一个逻辑:
我们能发现当超过setter.length 的一半时,此时的row的index应该是setterIndex - (setterIndex/2) + 1
所以新的一个实现是这样的:
在使用过程中的改变主要是:
源码:
改动点:
封装的bean对象:
封装的DataFrameWriter对象
测试用例:
mygithub