2015-04-26 2 views
0

Я использую текущие данные и примеры SNOMED, ​​и я хочу создать транзитивную таблицу закрытия, но что-то в моих настройках сервера MySQL mysql5.6 терпит неудачу.Код MYSQL для создания таблицы транзитивных замыканий не работает

Для тех, кто не знает, SNOMED - это медицинская база данных. Есть 2.1M отношения и 446697 концепций. Запрос останавливается на второй части - так что, я думаю, у него заканчивается ОЗУ. Но какие настройки я настраиваю и на что? join_buffer_size?

вот код:

DELIMITER ;; 
CREATE DEFINER=`snomed`@`localhost` PROCEDURE `createTc`() 
BEGIN 
    drop table if exists tc; 

    CREATE TABLE tc (
     source BIGINT UNSIGNED NOT NULL , 
     dest BIGINT UNSIGNED NOT NULL 
     ) ENGINE = InnoDB CHARSET=utf8; 
    insert into tc (source, dest) 
     select distinct rel.sourceid, rel.destinationid 
     from rf2_ss_relationships rel 
     inner join rf2_ss_concepts con 
      on rel.sourceid = con.id and con.active = 1 
     where rel.typeid = 116680003 # IS A relationship 
     and rel.active = 1; 
    REPEAT 
     insert into tc (source, dest) 
      select distinct b.source, a.dest 
      from tc a 
      join tc b on a.source = b.dest 
      left join tc c on c.source = b.source and c.dest = a.dest 
      where c.source is null; 
     set @x = row_count(); 
     select concat('Inserted ', @x); 
    UNTIL @x = 0 END REPEAT; 
    create index idx_tc_source on tc (source); 
    create index idx_tc_dest on tc (dest); 
END;; 
DELIMITER ; 
CREATE TABLE `rf2_ss_relationships` (
    `id` bigint(20) unsigned NOT NULL, 
    `effectiveTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `active` tinyint(4) DEFAULT '1', 
    `moduleId` bigint(20) unsigned NOT NULL, 
    `sourceId` bigint(20) unsigned NOT NULL, 
    `destinationId` bigint(20) unsigned NOT NULL, 
    `relationshipGroup` bigint(20) unsigned NOT NULL, 
    `typeId` bigint(20) unsigned NOT NULL, 
    `characteristicTypeId` bigint(20) unsigned NOT NULL, 
    `modifierId` bigint(20) unsigned NOT NULL, 
    PRIMARY KEY (`id`,`effectiveTime`), 
    KEY `moduleId_idx` (`moduleId`), 
    KEY `sourceId_idx` (`sourceId`), 
    KEY `destinationId_idx` (`destinationId`), 
    KEY `relationshipGroup_idx` (`relationshipGroup`), 
    KEY `typeId_idx` (`typeId`), 
    KEY `characteristicTypeId_idx` (`characteristicTypeId`), 
    KEY `modifierId_idx` (`modifierId`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

CREATE TABLE `rf2_ss_concepts` (
    `id` bigint(20) unsigned NOT NULL, 
    `effectiveTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `active` tinyint(4) DEFAULT NULL, 
    `moduleId` bigint(20) unsigned NOT NULL, 
    `definitionStatusId` bigint(20) unsigned NOT NULL, 
    PRIMARY KEY (`id`,`effectiveTime`), 
    KEY `moduleId_idx` (`moduleId`), 
    KEY `definitionStatusId_idx` (`definitionStatusId`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 
+0

я теперь использовать это: https://github.com/WestCoastInformatics/SNOMED-CT-Transitive-Closure сделать транзитивное замыкание в Java, а затем импортировать текстовый файл. он намного быстрее, чем mysql. – pgee70

ответ

2

Я не знаю, если это лучший ответ, но он работает ... Я изменил синтаксис создания таблицы для добавления индекса на создание - не после завершения. Я изменил настройки для innodb_buffer_pool_size = 8G

CREATE TABLE tc (
    source BIGINT UNSIGNED NOT NULL , 
    dest BIGINT UNSIGNED NOT NULL, 
    KEY source_idx (source), 
    KEy dest_idx (dest) 
    ) ENGINE = InnoDB CHARSET=utf8; 

даже до сих пор исполнение на моем i7 макинтош с SSD не был быстрым туздЫ, но он сделал работу, и переходная таблица закрытие 5180059 строк ....

mysql> call createTc; 
+-------------------------+ 
| concat('Inserted ', @x) | 
+-------------------------+ 
| Inserted 654161   | 
+-------------------------+ 
1 row in set (1 min 55.13 sec) 

+-------------------------+ 
| concat('Inserted ', @x) | 
+-------------------------+ 
| Inserted 1752024  | 
+-------------------------+ 
1 row in set (3 min 5.60 sec) 

+-------------------------+ 
| concat('Inserted ', @x) | 
+-------------------------+ 
| Inserted 2063816  | 
+-------------------------+ 
1 row in set (10 min 42.07 sec) 

+-------------------------+ 
| concat('Inserted ', @x) | 
+-------------------------+ 
| Inserted 275904   | 
+-------------------------+ 
1 row in set (28 min 5.49 sec) 

+-------------------------+ 
| concat('Inserted ', @x) | 
+-------------------------+ 
| Inserted 280   | 
+-------------------------+ 
1 row in set (46 min 29.78 sec) 

+-------------------------+ 
| concat('Inserted ', @x) | 
+-------------------------+ 
| Inserted 0    | 
+-------------------------+ 
1 row in set (1 hour 5 min 20.05 sec) 

Query OK, 0 rows affected (1 hour 5 min 20.05 sec) 
+0

, после этого я нашел реализацию Java, которая решает проблему намного быстрее. проверьте это: https://github.com/WestCoastInformatics/SNOMED-CT-Transitive-Closure/blob/master/src/main/java/com/wcinformatics/snomed/TransitiveClosureGenerator.java – pgee70

0

Я использую этот рекурсивный метод. При чтении отношений я уже добавил всех прямых потомков в список объектов-концептов (я использую hibernate), поэтому они доступны.

Затем я начинаю эту рекурсивную функцию, идя по списку понятий. См. Пример. Он ходит по каждой концепции по списку всех прямых родителей:

for (Sct2Concept c : concepts.values()) { 
    for(Sct2Relationship parentRelation : c.getChildOfRelationships()){ 
     addParentToList(concepts, sct2TransitiveClosureList, parentRelation, c); 
    } 
} 

Как вы можете видеть, запоминающий транзитивное замыкание представляет собой набор, так что проверки для уникальных значений на умном и очень созревший Java-библиотеке внутреннего кода.

private void addParentToList(Map<String, Sct2Concept> concepts, Set<Sct2TransitiveClosure> sct2TransitiveClosureList, Sct2Relationship parentRelation, Sct2Concept c){ 
     if(!parentRelation.isActive()) 
      return; 
     Sct2TransitiveClosure tc = new Sct2TransitiveClosure(parentRelation.getDestinationSct2Concept().getId(), c.getId()); 
     if(sct2TransitiveClosureList.add(tc)){ 
      Sct2Concept s = concepts.get(Long.toString(tc.getParentId())); 
      for(Sct2Relationship newParentRelation : s.getChildOfRelationships()){ 
       addParentToList(concepts, sct2TransitiveClosureList, newParentRelation, c); 
     } 
    } 
}