这是我遇到的问题, 我有1千万条数据 ,以前的业务涉及多表我都是用联合查询,都是多对一模式,现在公司要对业务改造,产品做成京东那种多特征类似这种,每种商品的特征是不一样(可能会有多个特征),根据分片出来的数据
我的数据导入是类似以下这种形式
<dataConfig>
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/dbname"
user="user-name"
password="password"/>
<document>
<entity name="outer"
query="select id,name,desc from mytable">
<field column="id" name="solr_id"/>
<field column="name" name="solr_name"/>
<entity name="inner"
query="select goodsAttrfrom another_table where id ='${outer.id}'">
<field column="goodsAttr" name="goodsAttr"/>
</entity>
</entity>
</document>
</dataConfig>
现在遇到的问题是 当我去查询主表mytable,然后还有个子查询another_table (another_table 是多条记录可能有几千万条数据)
我之前导数据是1千万2小时可以导完,改造成现在这种业务后 要8-10个小时,这种导数据速度 我无法忍受,于是去solr dih包源码转了转 找到解析每条Field的方法
于是找到了org.apache.solr.handler.dataimport .DocBuilder 下有个addFieldToDoc 这个方法,该方法的主要作用是解析查询的数据转换成Document 的Field
private void addFieldToDoc(Object value, String name, float boost, boolean multiValued, DocWrapper doc) {
if (value instanceof Collection) {
Collection collection = (Collection) value;
if (multiValued) {
for (Object o : collection) {
if (o != null)
doc.addField(name, o, boost);
}
} else {
if (doc.getField(name) == null)
for (Object o : collection) {
if (o != null) {
doc.addField(name, o, boost);
break;
}
}
}
} else if (multiValued) {
if (value != null) {
doc.addField(name, value, boost);
}
} else {
if (doc.getField(name) == null && value != null)
doc.addField(name, value, boost);
}
}
我的字段是数组格式存储于是我在判断是multiValued 的地方动刀子,现在是粗略为了完工判断字段写死(goodsAttr)的做的好的话应该是扩展
solr 的<field name="goods_attr" type="string" indexed="true" stored="true" multiValued="true"/> 加个strToArr="true"不过这要动大刀子,等以后有时间扩展
现在改成
private void addFieldToDoc(Object value, String name, float boost, boolean multiValued, DocWrapper doc) {
if (value instanceof Collection) {
Collection collection = (Collection) value;
if (multiValued) {
for (Object o : collection) {
if (o != null)
doc.addField(name, o, boost);
}
} else {
if (doc.getField(name) == null)
for (Object o : collection) {
if (o != null) {
doc.addField(name, o, boost);
break;
}
}
}
} else if (multiValued) {
if (value != null) {
if(name.equals("goodsAttr")){
String v = (String)value;
String[] a = v.split(",");
if(a != null && a.length > 0){
for (String str : a) {
doc.addField(name, str, boost);
}
}
}else{
doc.addField(name, value, boost);
}
}
} else {
if (doc.getField(name) == null && value != null)
doc.addField(name, value, boost);
}
}
也就是我之前子查询 我之前都把值存进 主表以逗号分割存进一个字段 叫 goodsAttr(例如:佩戴方式_头戴式,类型_耳麦),然后导数据对逗号分割的字符串处理
现在导数据速度又恢复到以前的2个多小时