0

我在 Ubuntu 13.04 上使用 mysql 5.5 来存储 URI 之间的相似性度量 [-1,1]。我的表格布局非常简单:

|--------------------------------------------------|
| uri1               | uri2                | value |
|--------------------------------------------------|
|http://foo.com/bar  | http://bar.net/foo  | 0.8   |
|http://foo.com/bar1 | http://bar.net/foo2 | 0.4   |
|--------------------------------------------------|

我想确保对于两个特定的 uri,存储的值不超过一个。因此,我使用以下 sql 来创建表:

CREATE  TABLE IF NOT EXISTS db.table(
  uri1 VARCHAR(255) NOT NULL ,
  uri2 VARCHAR(255) NOT NULL ,
  value DOUBLE NULL ,
  PRIMARY KEY (uri1, uri2),
  INDEX (value) )

不幸的是,当我批量插入数据(通过 Java JDBC)时,我得到如下异常:

java.sql.BatchUpdateException: Duplicate entry
 'http://xmlns.com/foaf/0.1/Document-http://purl.org/linked-data/c' 
for key 'PRIMARY'

主键似乎不足以存储两个 URI,因此当前缀相同(通常在我的数据中)时,我会得到重复的条目异常。我已经检查并没有插入“真正的”重复项。有没有办法设置主键的长度,以便它始终完全包含两个 URI?或者通常有更好的方法来建模数据?

每当我插入数据时,我不想检查是否已经存在具有提供的 uri1 和 uri2 的行,而是如果这可能实际发生(它不应该)处理异常。因此,我认为,仅使用递增整数作为主键是不可行的。

在我的应用程序中,我将为不同的度量创建几个这样的表,并且以后可能希望通过 uri1 和 uri2 将它们连接起来,以便我得到一个包含来自不同表的结果,其中包含一对特定 uris 的所有值。

我发现了别的东西:我在 Java 中设置了这样的连接:

conn = DriverManager.getConnection(
 "jdbc:mysql://localhost/db?useServerPrepStmts=false&rewriteBatchedStatements=true",
 "user","pass");

当我不使用“rewriteBatchedStatements=true”时,它似乎工作正常。不幸的是,我真的必须使用它,因为如果我不这样做,批量插入会慢几个数量级。

这是额外请求的代码:

//Initialized in Constructor
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/db?useServerPrepStmts=false&rewriteBatchedStatements=true",
                "user","pass");

PreparedStatement pst = conn.prepareStatement(String.format("INSERT INTO %s.%s values (?, ?, ?)", dbName, tableName));
//

public void queue(ResDescriptor row, ResDescriptor column, double simil) {
    if(!operational()) return;
    try {
        String uri1 = row.getType();
        String uri2 = column.getType();
        pst.setString(1, uri1);
        pst.setString(2, uri2);
        pst.setDouble(3, simil);            
        pst.addBatch();

        if(++batchCount%maxBatch == 0){
            pst.executeBatch();
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

getType() 总是返回一个 URI-String,并且可以确保 queue() 方法不会使用相同的参数调用两次。

非常感谢您的任何建议!

4

1 回答 1

0

我很抱歉回答我自己的问题,但经过数小时质疑我的理智后,我终于找到了问题所在。它与密钥的长度无关,这很好。异常消息似乎在某些时候被截断了。真正的问题是 latin1_swedish_ci 中的小i意味着键不区分大小写!事实上,我的数据确实包含两个只是大小写不同的 URI。添加

DEFAULT CHARACTER SET utf8 COLLATE utf8_bin

到表创建语句解决了这个问题。

谢谢您的意见。不过,我无法真正理解为什么这种行为是默认行为。

于 2013-08-09T02:43:40.767 回答