2015-02-06 4 views
1

Запуск Mysql V5.6.22, выполняющий сложный запрос в правильно проиндексированной базе данных, время отклика первоначально очень медленно (10 секунд). Последующие запросы (для разных элементов) очень чувствительны (50 мс). поэтому я думаю, что кеши запросов выполняют свою работу, но как я могу свести к минимуму начальный медленный ответ?Slow * initial * mysql query

База данных - это справочная база медицинских баз с внешней поддержкой (SNOMED), и я использую рекомендуемые виды для текущих снимков - I думаю, что эти ограничения являются ограничением по скорости.

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

Итак, мой вопрос: существует ли параметр mysql, который используется для того, как долго сохраняются эти кеши, или я должен использовать другой подход и не использовать представления (данные для SNOMED обновляются 2x год, а в другой подобной базе данных для лекарств существуют ежемесячные выпуски.

Некоторые из вас хотели бы видеть запрос, так что здесь идет. Предупреждение, что это немного сложно, а количество строк для базовых запросов дано в комментариях ... ;-)

SELECT DISTINCT concat(c.id, '::', c.effectiveTime) as id, `d1`.`term` as label, `d2`.`term` 
FROM (`snomed`.`rf2_ss_refset` as refset) 
JOIN `snomed`.`rf2_ss_concepts` as c ON `c`.`id` = `refset`.`referencedCOmponentId` 
JOIN `snomed`.`rf2_ss_descriptions` as d1 ON `d1`.`conceptId` = `refset`.`referencedComponentId` 
JOIN `snomed`.`rf2_ss_descriptions` as d2 ON `d2`.`conceptId` = `d1`.`conceptId` 
JOIN `snomed`.`rf2_ss_language_refset` as lang ON `lang`.`referencedComponentId` = `d1`.`id` 
WHERE `refset`.`refSetId` = 32570071000036102 
AND `refset`.`active` = 1 
AND `d2`.`typeId` = 900000000000013009 
AND `d1`.`active` = 1 
AND `d2`.`active` = 1 
AND `d1`.`moduleId` = 900000000000207008 
AND `d2`.`moduleId` = 900000000000207008 
AND `lang`.`active` = 1 
AND `lang`.`acceptabilityId` = 900000000000548007 
AND `d2`.`term` like "hypertension%" 
ORDER BY `d1`.`term`, `d2`.`term` 

ГДЕ:

CREATE TABLE `rf2_ss_refset` (
    `id` char(36) COLLATE utf8_unicode_ci NOT NULL, 
    `effectiveTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `active` smallint(1) NOT NULL, 
    `moduleId` bigint(20) unsigned NOT NULL, 
    `refSetId` bigint(20) unsigned NOT NULL, 
    `referencedComponentId` bigint(20) unsigned NOT NULL, 
    PRIMARY KEY (`id`,`effectiveTime`), 
    KEY `moduleId_idx` (`moduleId`), 
    KEY `refSetId_idx` (`refSetId`), 
    KEY `referencedComponentId_idx` (`referencedComponentId`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

CREATE ALGORITHM=UNDEFINED DEFINER=`snomed`@`localhost` SQL SECURITY DEFINER VIEW `rf2_ss_concepts` 
AS SELECT 
    `t1`.`id` AS `id`, 
    `t1`.`effectiveTime` AS `effectiveTime`, 
    `t1`.`active` AS `active`, 
    `t1`.`moduleId` AS `moduleId`, 
    `t1`.`definitionStatusId` AS `definitionStatusId` 
FROM `rf2_full_concepts` `t1` where (`t1`.`effectiveTime` = (select max(`t2`.`effectiveTime`) from `rf2_full_concepts` `t2` where (`t1`.`id` = `t2`.`id`))); 

CREATE ALGORITHM=UNDEFINED DEFINER=`snomed`@`localhost` SQL SECURITY DEFINER VIEW `rf2_ss_descriptions` 
AS SELECT 
    `t1`.`id` AS `id`, 
    `t1`.`effectiveTime` AS `effectiveTime`, 
    `t1`.`active` AS `active`, 
    `t1`.`moduleID` AS `moduleID`, 
    `t1`.`conceptId` AS `conceptId`, 
    `t1`.`languageCode` AS `languageCode`, 
    `t1`.`typeID` AS `typeID`, 
    `t1`.`term` AS `term`, 
    `t1`.`caseSignificanceId` AS `caseSignificanceId` 
FROM `rf2_full_descriptions` `t1` where (`t1`.`effectiveTime` = (select max(`t2`.`effectiveTime`) from `rf2_full_descriptions` `t2` where (`t1`.`id` = `t2`.`id`))); 

CREATE ALGORITHM=UNDEFINED DEFINER=`snomed`@`localhost` SQL SECURITY DEFINER VIEW `rf2_ss_language_refset` 
AS SELECT 
    `t1`.`id` AS `id`, 
    `t1`.`effectiveTime` AS `effectiveTime`, 
    `t1`.`active` AS `active`, 
    `t1`.`moduleId` AS `moduleId`, 
    `t1`.`refSetId` AS `refSetId`, 
    `t1`.`referencedComponentId` AS `referencedComponentId`, 
    `t1`.`acceptabilityId` AS `acceptabilityId` 
FROM `rf2_full_language_refset` `t1` where (`t1`.`effectiveTime` = (select max(`t2`.`effectiveTime`) from `rf2_full_language_refset` `t2` where (`t1`.`id` = `t2`.`id`))); 

CREATE ALGORITHM=UNDEFINED DEFINER=`snomed`@`localhost` SQL SECURITY DEFINER VIEW `rf2_ss_relationships` 
AS SELECT 
    `t1`.`id` AS `id`, 
    `t1`.`effectiveTime` AS `effectiveTime`, 
    `t1`.`active` AS `active`, 
    `t1`.`moduleId` AS `moduleId`, 
    `t1`.`sourceId` AS `sourceId`, 
    `t1`.`destinationId` AS `destinationId`, 
    `t1`.`relationshipGroup` AS `relationshipGroup`, 
    `t1`.`typeId` AS `typeId`, 
    `t1`.`characteristicTypeId` AS `characteristicTypeId`, 
    `t1`.`modifierId` AS `modifierId` 
FROM `rf2_full_relationships` `t1` where (`t1`.`effectiveTime` = (select max(`t2`.`effectiveTime`) from `rf2_full_relationships` `t2` where (`t1`.`id` = `t2`.`id`))); 

#select count(*) from rf2_full_concepts # 507046 
CREATE TABLE `rf2_full_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; 

#select count(*) from rf2_full_descriptions # 1486373 
CREATE TABLE `rf2_full_descriptions` (
    `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, 
    `conceptId` bigint(20) unsigned NOT NULL, 
    `languageCode` char(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT 'en', 
    `typeID` bigint(20) unsigned NOT NULL, 
    `term` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `caseSignificanceId` bigint(20) unsigned NOT NULL, 
    PRIMARY KEY (`id`,`effectiveTime`), 
    KEY `moduleID_idx` (`moduleID`), 
    KEY `conceptId_idx` (`conceptId`), 
    KEY `typeID_idx` (`typeID`), 
    KEY `caseSignificanceId_idx` (`caseSignificanceId`), 
    KEY `term_idx` (`term`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

#select count(*) from rf2_full_relationships = 4582286 
CREATE TABLE `rf2_full_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; 

#select count(*) from rf2_full_language_refset # 624467 
CREATE TABLE `rf2_full_language_refset` (
    `id` char(36) COLLATE utf8_unicode_ci NOT NULL, 
    `effectiveTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `active` smallint(1) NOT NULL, 
    `moduleId` bigint(20) unsigned NOT NULL, 
    `refSetId` bigint(20) unsigned NOT NULL, 
    `referencedComponentId` bigint(20) unsigned NOT NULL, 
    `acceptabilityId` bigint(20) unsigned NOT NULL, 
    PRIMARY KEY (`id`,`effectiveTime`), 
    KEY `moduleId` (`moduleId`), 
    KEY `refSetId` (`refSetId`), 
    KEY `referencedComponentId` (`referencedComponentId`), 
    KEY `acceptabilityId` (`acceptabilityId`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 
+0

путем преобразования представлений в таблицы я могу подтвердить, что это замедление, замедляющее его. теперь вопрос действительно ради интересов - я думаю, что мне просто придется мириться с более длительным временем простоя, связанным с обновлениями - слишком дорогими взгляды! – pgee70

+0

Вы могли бы опубликовать план выполнения запроса для запроса? Просто посмотреть, что происходит? – Olli

ответ

2

Диагностирование чужой сервер без всех частей головоломки трудно, так что я буду делать следующие предположения (поправьте меня, если я ошибаюсь):

  1. Это не работает на БД-класса сервер
  2. конфигурационный MySQL не были особенно настроены для выполнения этой задачи

для примеров вы показали свои таблицы выглядят более индексированными, и из-за большой набор данных, я могу себе представить, что самый большой файл индекс слишком большой, чтобы вписаться в индексный кеш MySQL.

Без дополнительной информации об окружающей среде кажется, что поведение, которое вы описываете, зависит от настроенных буферов. На этом этапе ОС входит и буферизирует БД в памяти.

Когда вы перезапускаете MySQL, он запрашивает хороший и быстрый, поскольку ОС по-прежнему хранит файлы в своих буферах. Когда вы прекратите доступ к БД, ОС в конечном итоге отключит файлы, и вы вернетесь к медленному первоначальному запросу.

Я видел такое же поведение на больших индексах, которые превышают настроенный размер буфера, но это намного больший набор данных. Конфигурирование БД для увеличения буферов для индексов и табличных данных решило мою конкретную проблему. В моем случае скорость запроса снизилась с 10-15 секунд до миллисекунд.

http://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_buffer_pool_size

Если у вас есть немного свободного ОЗУ, попробуйте повысит размер буферного пула несколько. Размер по умолчанию - 128 МБ, а самый большой индексный файл будет примерно 279 МБ (64 байта * 4582 286 строк). Чтобы начать, попробуйте установить значение в своей конфигурации на 512 МБ. Перезапустите, повторите попытку. Если это еще не здорово, добавьте еще 128 Мб и повторите, пока он не сработает. Если эта БД находится на выделенной машине, установите значение довольно высокое (50-75% общей ОЗУ) должно быть безопасным в зависимости от вашей установки.

Быстрый Google придумал хороший справочник о том, какие значения конфигурации для скрипки. http://www.tocker.ca/2013/09/17/what-to-tune-in-mysql-56-after-installation.html

+0

Спасибо. Я принял ваш ответ. Я буду перекодировать базу данных, чтобы использовать таблицы вместо представлений - потому что я не получаю отставание от таблиц, используя больше бара, как вы предлагаете, будет дорого! – pgee70