Java MySQL查询在大型实例上发生变异:
我目前正在计算一个1500万条记录的数据库。前7个工厂刚刚结束,但现在我的更新查询开始出现问题: 现在&然后一个随机的字母变成了一些吉卜里什语。 在java中,我通过以下操作生成查询:Java MySQL查询在大型实例上发生变异:,java,mysql,large-data-volumes,large-data,Java,Mysql,Large Data Volumes,Large Data,我目前正在计算一个1500万条记录的数据库。前7个工厂刚刚结束,但现在我的更新查询开始出现问题: 现在&然后一个随机的字母变成了一些吉卜里什语。 在java中,我通过以下操作生成查询: String updateSql = "UPDATE VanNaar SET time = CASE ID "; for (int i = 0; i < routes.size(); i++) { updateSql += " WHEN " + routes.get(
String updateSql = "UPDATE VanNaar SET time = CASE ID ";
for (int i = 0; i < routes.size(); i++) {
updateSql += " WHEN " + routes.get(i).ID + " THEN " + routes.get(i).driveTime;
}
updateSql += " END, ";
updateSql += " distance = CASE ID ";
for (int i = 0; i < routes.size(); i++) {
updateSql += " WHEN " + routes.get(i).ID + " THEN " + routes.get(i).distance;
}
updateSql += " END WHERE id IN (";
for (int i = 0; i < routes.size(); i++) {
updateSql += routes.get(i).ID + ",";
}
updateSql = updateSql.substring(0, updateSql.length() - 1);
updateSql += ");";
或
请注意最后一个例子的古怪风格,请注意粗体字:
…MySQL服务器版本,以便在**附近使用正确的语法,当7228125时,然后是48590.0;当7228126时,然后是47910.0;当7228127时,然后是…
更新:
情况似乎越来越糟
Unknown column '9°22331' in 'where clause'
我不是Java专家,但您不应该首先使用Java吗?甚至可能使用一个?您可以使用stringbuilder而不是
updateSql += " WHEN " + routes.get(i).ID + " THEN " + routes.get(i).driveTime;
在任何地方你都会做类似的事情
myStrngBldr.append(" WHEN ? THEN ?");
或
如果支持命名参数(不知道),然后添加实际参数:
myPrepdStmt = myConn.prepareStatement(myStrngBldr.toString());
myPrepdStmt.setInt(1, routes.get(i).ID);
myPrepdStmt.setFloat(2, routes.get(i).driveTime);
...
myPrepdStmt.executeUpdate();
我应该帮助你
究竟是什么导致了“奇怪的畸形字符串”:我不知道。我的最佳猜测是,由于要连接字符串,所以必须在所有ID和其他非字符串值上使用类似.ToString()的内容。也许,不知何故,这些值被解释为字符码(因为它们没有显式地转换为字符串),从而导致奇怪的字符
另一个猜测是:在将查询发送到数据库之前,您是否真的在内存中构建了1500万个查询?还是每个查询都分别发送到数据库?可能您试图在内存中存储一个巨大的ass字符串会导致一些问题(尽管它不应该导致您在这里描述的问题)。我不是Java专家,但您不应该首先使用a吗?甚至可能使用一个?您可以使用stringbuilder而不是
updateSql += " WHEN " + routes.get(i).ID + " THEN " + routes.get(i).driveTime;
在任何地方你都会做类似的事情
myStrngBldr.append(" WHEN ? THEN ?");
或
如果支持命名参数(不知道),然后添加实际参数:
myPrepdStmt = myConn.prepareStatement(myStrngBldr.toString());
myPrepdStmt.setInt(1, routes.get(i).ID);
myPrepdStmt.setFloat(2, routes.get(i).driveTime);
...
myPrepdStmt.executeUpdate();
我应该帮助你
究竟是什么导致了“奇怪的畸形字符串”:我不知道。我的最佳猜测是,由于要连接字符串,所以必须在所有ID和其他非字符串值上使用类似.ToString()的内容。也许,不知何故,这些值被解释为字符码(因为它们没有显式地转换为字符串),从而导致奇怪的字符
另一个猜测是:在将查询发送到数据库之前,您是否真的在内存中构建了1500万个查询?还是每个查询都分别发送到数据库?也许你试图在内存中存储一个巨大的ASS字符串会导致一些问题(虽然它不应该引起你在这里描述的问题)。 < P>你可能想考虑用“两个代码> CASE < /代码>选择器和一个<代码>在中替换每一行的单独的<代码>更新< /Cord>语句。我知道问题并非由此引起,但这可能是一个更干净、更有效的解决方案。如果DB连接器支持每次执行多个语句,则可以执行以下操作:
int batchSize = 0;
StringBuilder sb = new StringBuilder();
for (Route r: routes) {
sb.append("UPDATE VanNaar SET")
.append(" time = '").append(r.driveTime).append("',")
.append(" distance = '").append(r.distance).append("'")
.append(" WHERE ID = '").append(r.ID).append("'; ");
if (++batchSize == BATCH_SIZE) {
connector.exec(sb.toString());
sb = new StringBuilder();
batchSize = 0;
}
}
if (sb.length() > 0) {
connector.exec(sb.toString());
}
这将使StringBuilder
负责将底层值类型转换为String
。如果driveTime
、distance
或ID
已经是字符串,则必须使用适当的JDBC方法正确地转义它们
您可能会更好地使用准备好的语句,因为它们会自动处理SQL注入问题。
< P>您可能想考虑用“<代码> CASE <代码> >选择器和一个代码>在< <代码> >中,用个别的<代码>更新< /COD>语句替换巨型更新。一行我知道问题并非由此引起,但这可能是一个更干净、更有效的解决方案。如果DB连接器支持每次执行多个语句,则可以执行以下操作:int batchSize = 0;
StringBuilder sb = new StringBuilder();
for (Route r: routes) {
sb.append("UPDATE VanNaar SET")
.append(" time = '").append(r.driveTime).append("',")
.append(" distance = '").append(r.distance).append("'")
.append(" WHERE ID = '").append(r.ID).append("'; ");
if (++batchSize == BATCH_SIZE) {
connector.exec(sb.toString());
sb = new StringBuilder();
batchSize = 0;
}
}
if (sb.length() > 0) {
connector.exec(sb.toString());
}
这将使StringBuilder
负责将底层值类型转换为String
。如果driveTime
、distance
或ID
已经是字符串,则必须使用适当的JDBC方法正确地转义它们
对于这类事情,您最好按照的建议使用预先准备好的语句,因为它们会自动处理SQL注入问题。与
routes.get(i).ID
和routes.get(i).distance相关联的类型是什么?与routes.get(i)相关联的类型是什么.ID
和路由.get(i).distance
?我正在批处理per(5000个请求,因此后一个注释不适用)。您的方法似乎确实有效。非常感谢。令人窒息的是,它似乎表现得更好。我正在批处理per(5000个请求,因此后一个注释不适用)。您的方法似乎确实有效。非常感谢。令人窒息的是,它似乎也表现得更好。