首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当表有某种关系时,即使在使用多线程之后,也要花很长时间在mysql表中插入行。

当表有某种关系时,即使在使用多线程之后,也要花很长时间在mysql表中插入行。
EN

Stack Overflow用户
提问于 2011-01-14 18:19:43
回答 2查看 2.3K关注 0票数 1

我想通过JDBC将200000行插入到表中,connection.My表有三列:DISTRICT1(Id、Name、country).I使用多线程执行插入操作,它在不到1 minutes.Then中插入数据--我再次尝试对DISTRICT2(Id、Name、country)表执行类似的操作,在这种情况下,需要很长时间的foreign-key-relationship (超过2小时)来插入行(就像对单线程一样),与两个表之间唯一的区别是DISTRICT2表有一个字段Id,该字段通过链接到其他表,而DISTRICT1表没有这种关系。还有一个区别是mysql引擎,DISTRICT1有ENGINE=MyISAM,而为DISTRICT2提供ENGINE=INNODB,当我使用语句 .Does代替语句.Does时,它也给了java.lang.OutOfMemoryError一些与连接池有关的信息

请告诉,当表有某种关系时,为什么要花很长时间?我使用了相同的程序代码来插入两个表。

代码语言:javascript
复制
public static void main(String[] args) {
  ExecutorService executor = Executors.newFixedThreadPool(10);
  for (int i = 1; i <200001; i=i+10000) {
      Runnable worker = new MyRunnable4District(i);
          executor.execute(worker);
      }
  executor.shutdown();
 }

类MyRunnable4District如下所示

代码语言:javascript
复制
public class MyRunnable4District implements Runnable {
 public int size;

 public MyRunnable4District(int n) {
  this.size = n;
 }

 public void run() {
  Connection con = null;
  try {

   Class.forName("com.mysql.jdbc.Driver");
   con = DriverManager.getConnection("jdbc:mysql://localhost/project",
     "root", "root");

   String[] countries = { "ARGENTINA", "US", "UK", "INDIA", "UKRAINE",
     "CHINA" };

   for (int id = size; id < size + 10001; id++) {
    int districtId = id;
    String districtName ="columbia"+id;
    String districtCountry = countries[id % 6];
    String query="INSERT INTO district "+"VALUES ("+districtId+",'"+districtName+"','"+districtCountry+"')";
    //PreparedStatement stmnt =con.prepareStatement(query);
    Statement stmnt =con.createStatement();
    stmnt.executeUpdate(query);
   }

  } catch (ClassNotFoundException e) {
   System.out.println(e.getMessage());
  } catch (SQLException e) {
   System.out.println(e.getMessage());
  } finally {
   try {
    con.close();
    System.out.println("thread number with size "+size+" completed");
   } catch (SQLException e) {
    e.printStackTrace();
   }

  }

 }
}
EN

回答 2

Stack Overflow用户

发布于 2011-01-14 18:22:11

你没有清理你的资源。在你使用完之后,你应该对你的陈述进行

但是,使用PreparedStatement并使用不同的参数重用它将是一个更好的主意。

另外,您可能需要考虑使用负载数据信息

票数 0
EN

Stack Overflow用户

发布于 2011-01-22 20:36:49

您应该尝试多值插入。例如:

代码语言:javascript
复制
INSERT INTO district VALUES (id1,name1,country1),(id2,name2,country2),(id3,name3,country3);

这可以提供显著的性能提升,特别是在连接到远程服务器时需要这样做的时候。除了减少网络往返(甚至本地机器上的进程外调用)之外,服务器还必须处理更少的查询。另外,如果为InnoDB启用了自动提交,那么现在每个批处理将有一个事务,而不是每个语句一个。

如果您将rewriteBatchedStatements选项设置为true,Connector/ JDBC驱动程序将为您执行此操作。我认为这个特性是在3.1.x驱动程序发行版中为像您这样的简单插入添加的。在以后的版本中,rewriteBatchedStatements得到了增强,以支持更复杂的语句。在此页上搜索rewriteBatchedStatements。

或者可以重写代码来手动构造多值insert语句。需要注意的一件事是最大的数据包大小。您需要确保insert语句保持在该值以下。因此,要么在导入数据时使封包变得非常大,要么在批处理接近max_allowed_packet时将其分解。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4694474

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档