2015-02-06 311 views
1

運行Mysql V5.6.22,在正確索引的數據庫上運行復雜查詢時,響應時間最初非常緩慢(10秒)。隨後的查詢(針對不同的項目)非常敏感(50毫秒)。所以我猜查詢緩存正在做他們的工作 - 但我如何最小化最初的慢響應?緩慢*初始* mysql查詢

該數據庫是一個外部維護的醫療數據庫(SNOMED),我使用推薦視圖爲當前快照 - 我認爲這些視圖是對速度的限制。

奇怪地重新啓動mysql並沒有什麼區別 - 它似乎是時間事情 - 如果數據庫沒有被使用一段時間,它只需要很長時間就可以啓動。

所以我的問題是,是否有一個MySQL設置用於多久這些緩存保留或應該我使用不同的方法,而不是使用視圖(SNOMED的數據更新2年,並在另一個類似的數據庫對於藥品有每月發佈。?

你們有些人希望看到這裏的查詢。警告它確實有點棘手,基本查詢的行數在評論中給出... ;-)

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` 

WHERE:

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 2015-02-06 12:04:08

+0

你可以發佈查詢的查詢執行計劃嗎?只是爲了看看發生了什麼? – Olli 2015-02-06 12:51:58

回答

2

診斷別人的服務器,而所有謎題的部分是困難的,所以我會做如下假設(糾正我,如果我錯了):

  1. 這不是一個DB-級運行服務器
  2. MySQL的配置還沒有被特別地被配置爲例子,你表現出你的表看起來超指數的這個任務

,並且由於大型數據集,我可以想像,最大的索引文件太大而不適合MySQL的索引緩存。

沒有關於環境的更多信息,看起來您所描述的行爲取決於配置的緩衝區。此時,操作系統進入並將數據庫緩存在內存中。

當您重新啓動MySQL時,它查詢的很好,而且速度很快,因爲操作系統仍將文件保存在緩衝區中。當您停止訪問數據庫時,操作系統將最終取消緩衝文件,並且您將回到最初的慢查詢。

我已經看到大於超過配置的緩衝區大小的大型索引上的相同行爲,但是這是一個更大的一組數據。配置數據庫具有更大的索引和表數據緩衝區解決了我的特殊問題。在我的情況下,查詢速度從10-15秒降到毫秒。

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

如果你有一些空閒內存,嘗試有所加大了緩衝池大小。 默認大小爲128Mb,並且您的最大索引文件大約爲279Mb(64字節* 4,582,286行)。 要開始,請嘗試將配置中的值設置爲512Mb。重新啓動,重新測試。如果它還不是很好,請再添加一個128Mb並重復,直到它工作。 如果此DB位於專用機器上,請根據您的設置將該值設置得相當高(總RAM的50-75%)應該是安全的。

一個快速的谷歌提出了一個很好的指導什麼配置值來擺弄。 http://www.tocker.ca/2013/09/17/what-to-tune-in-mysql-56-after-installation.html

+0

謝謝。我已經接受你的答案。我將重新編碼數據庫以使用表格而不是視圖 - 因爲我不會使用表格來獲得滯後,因爲您建議使用更多的內存將會很昂貴! – pgee70 2015-02-07 01:36:36