首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >复合主键太长了吗?

复合主键太长了吗?
EN

Stack Overflow用户
提问于 2013-08-09 03:50:24
回答 1查看 607关注 0票数 0

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

代码语言:javascript
复制
|--------------------------------------------------|
| uri1               | uri2                | value |
|--------------------------------------------------|
|http://foo.com/bar  | http://bar.net/foo  | 0.8   |
|http://foo.com/bar1 | http://bar.net/foo2 | 0.4   |
|--------------------------------------------------|

我希望确保对于两个特定的uris,存储的值不超过一个。因此,我使用sql中的以下语句来创建表:

代码语言:javascript
复制
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),我得到如下异常:

代码语言:javascript
复制
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中设置了如下连接:

代码语言:javascript
复制
conn = DriverManager.getConnection(
 "jdbc:mysql://localhost/db?useServerPrepStmts=false&rewriteBatchedStatements=true",
 "user","pass");

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

以下是额外请求的代码:

代码语言:javascript
复制
//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字符串,并且可以确保queue()方法永远不会用相同的参数调用两次。

非常感谢您的任何建议!

EN

回答 1

Stack Overflow用户

发布于 2013-08-09 10:43:41

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

代码语言:javascript
复制
DEFAULT CHARACTER SET utf8 COLLATE utf8_bin

表create语句解决了这个问题。

感谢您的评论。不过,我真的不能理解为什么这个行为是默认的。

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

https://stackoverflow.com/questions/18134835

复制
相关文章

相似问题

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