2013-08-08 3 views
0

우분투 13.04에서 mysql 5.5를 사용하여 유사성 측정 값 [-1,1]을 URI 사이에 저장합니다. 내 테이블 레이아웃은 매우 간단합니다 :복합 기본 키가 너무 깁니다.

|--------------------------------------------------| 
| 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을 사용

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

는 것 같다 : 나는 (자바 JDBC를 통해) 일괄 삽입 데이터를 생각 할 때, 불행하게도

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)) 

을, 나는 다음과 같은 예외를 얻을 기본 키처럼 두 URI를 저장할만큼 길지 않아 접두어가 동일 할 때 중복 항목 예외가 발생합니다 (내 데이터에 자주 있음). 나는 "실제"중복이 삽입되어 있는지 확인했다. 기본 키의 길이를 설정하여 항상 두 URI가 완전히 포함되도록하는 방법이 있습니까? 아니면 일반적으로 데이터를 모델링하는 더 좋은 방법이 있습니까?

데이터를 삽입 할 때마다 제공된 uri1 및 uri2가있는 행이 이미 있는지 확인하고 싶지 않지만, 실제로 발생하지 않는 경우 (예외적으로 처리해야 함) 예외를 처리해야합니다. 따라서 기본 키로 증분 정수를 사용하는 것은 실현 불가능합니다.

내 응용 프로그램에서는 다양한 측정을 위해 이와 같은 여러 테이블을 만들고 나중에 uri1과 uri2에 합류시켜 결과가 서로 다른 테이블의 특정 쌍에 대한 모든 값을 포함하도록 할 수 있습니다. uris.

내가 뭔가를 발견 :

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 문자열을 반환하고이 큐() 메소드가 결코 같은 매개 변수를 두 번 호출되지 않도록 보장 :

는 여기에 추가로 요청 코드입니다.

제안 해 주셔서 감사합니다.

+0

기본 키가 너무 길면 테이블을 만들 때 오류가 발생했을 수 있습니다. InnoDB의 최대 길이는 767이고, MyISAM의 경우 최대 길이는 1000입니다. (검증하지는 않았지만) 키 길이가 그 아래에옵니다. 일괄 적재중인 파일에 dup이있을 가능성이 있습니까? –

+0

테이블은 어떤 데이터 정렬을 사용합니까? 그건 바이트 당 필요한 바이트를 결정합니다 ... – PinnyM

+0

"latin1_swedish_ci"나는 그게 무슨 뜻인지, 왜 "swedish"인지 정직하지는 않습니다. "rewriteBatchedStatements = true"에 대해 찾은 것을 추가했습니다. – feob

답변

0

내 자신의 질문에 대답하는 것이 유감이지만 내 정신을 질문하는 시간이 지나면 마침내 문제가 발견되었습니다. 그것은 열쇠의 길이와 아무 상관이 없습니다. 예외 메시지가 일부 지점에서 잘 렸습니다. 진짜 문제는 latin1_swedish_ci의 작은 i은 키가 대소 문자를 구분하지 않는다는 것을 의미합니다. 실제로 제 데이터에는 대문자 만 다른 두 개의 URI가 포함되어 있습니다. 더하기

DEFAULT CHARACTER SET utf8 COLLATE utf8_bin 

테이블 만들기 문으로 문제를 해결했습니다.

의견을 보내 주셔서 감사합니다. 그래도이 동작이 왜 기본인지 이해할 수는 없습니다.

관련 문제