And*_*rit 1 mysql optimization caching
我有MySQL DB,我总是问同样的"问题",我改变的只是查询中的VIN变量.
更具体地说,我向你展示了2个查询:第一个有VIN:(U5YFF24128L064909需要0.0002秒)
SELECT c.vin, c.case_id, c.claimnumber, c.platenumber, c.axrmrs_id,
c.insurer_memberid, c.country, c.date_created, c.totalloss,
c.lastcalc_manufacturer_code, c.lastcalc_model_code, c.lastcalc_submodel_code,
c.audavin_triggered, c.accident_date, c.registration_date,
c.manufacturing_year, cl.spareparts, cl.totalcosts, cl.laborhours,
cl.laborcosts, cl.calculationdate, cl.paintlabor, cl.paintmaterial,
cl.currency, car.manufacturer, car.model, car.submodel,
IFNULL(org.name, 0) as orgName, GROUP_CONCAT(DISTINCT IF(po.repairmethod LIKE 'L%',
po.text,NULL)
ORDER BY 1) AS textL, GROUP_CONCAT(DISTINCT IF(po.repairmethod = 'E',
po.text,NULL
)
ORDER BY 1) AS textE , GROUP_CONCAT(DISTINCT IF(po.repairmethod != 'E'
OR (po.repairmethod = 'E'
AND po.guidenumber = 'N/A'
)
AND po.repairmethod NOT LIKE 'L%',po.text, NULL
)
ORDER BY 1
) AS textO
FROM axnmrs_cases AS c
LEFT JOIN axnmrs_calculations as cl on c.case_id = cl.case_id
AND c.country = cl.country
LEFT JOIN axnmrs_positions as po on c.case_id = po.case_id
LEFT JOIN car_type as car on car.manufacturer_code = c.lastcalc_manufacturer_code
AND car.main_type = c.lastcalc_model_code
AND car.subtype_code = c.lastcalc_submodel_code
LEFT JOIN organization_list as org on org.memberId = c.insurer_memberid
WHERE c.vin= 'U5YFF24128L064909'
GROUP BY c.vin, c.case_id, c.axrmrs_id
Run Code Online (Sandbox Code Playgroud)
和第二个VIN = VF38BRHZE80728805 (这需要2.4387秒)
SELECT c.vin, c.case_id, c.claimnumber, c.platenumber, c.axrmrs_id,
c.insurer_memberid, c.country, c.date_created, c.totalloss,
c.lastcalc_manufacturer_code, c.lastcalc_model_code, c.lastcalc_submodel_code,
c.audavin_triggered, c.accident_date, c.registration_date,
c.manufacturing_year, cl.spareparts, cl.totalcosts, cl.laborhours,
cl.laborcosts, cl.calculationdate, cl.paintlabor, cl.paintmaterial,
cl.currency, car.manufacturer, car.model, car.submodel,
IFNULL(org.name, 0) as orgName, GROUP_CONCAT(DISTINCT IF(po.repairmethod LIKE 'L%',
po.text,NULL)
ORDER BY 1) AS textL, GROUP_CONCAT(DISTINCT IF(po.repairmethod = 'E',
po.text,NULL
)
ORDER BY 1) AS textE , GROUP_CONCAT(DISTINCT IF(po.repairmethod != 'E'
OR (po.repairmethod = 'E'
AND po.guidenumber = 'N/A'
)
AND po.repairmethod NOT LIKE 'L%',po.text, NULL
)
ORDER BY 1
) AS textO
FROM axnmrs_cases AS c
LEFT JOIN axnmrs_calculations as cl on c.case_id = cl.case_id
AND c.country = cl.country
LEFT JOIN axnmrs_positions as po on c.case_id = po.case_id
LEFT JOIN car_type as car on car.manufacturer_code = c.lastcalc_manufacturer_code
AND car.main_type = c.lastcalc_model_code
AND car.subtype_code = c.lastcalc_submodel_code
LEFT JOIN organization_list as org on org.memberId = c.insurer_memberid
WHERE c.vin= 'VF38BRHZE80728805'
GROUP BY c.vin, c.case_id, c.axrmrs_id
Run Code Online (Sandbox Code Playgroud)
我不知道为什么会发生这种情况所以我尝试分析所以我在PHPMYADMIN中使用"PROFILE"函数,它在屏幕上返回如下结果:VIN: U5YFF24128L064909

和VIN :( VF38BRHZE80728805显然操作时间更长)

因为我不能谷歌任何有用的东西我也尝试EXPLAIN SELECT查询,如下所示:对于VIN: U5YFF24128L064909

从这个解释我认为我在car_type表上做了很好的查询应该写得更好,但是它不会改变同一查询的速度只是用不同的VIN号.
我也在想我的第一个QUERY刚从CACHE返回,第二个来自DB.所以我尝试再次进行两次查询.而且两者都和以前一样.
有谁能帮我找到这个查询的问题吗?我做错了什么?
感谢您的任何建议,因为我已经迷失了!
编辑:在car_type表我对指标:manufacturer_code,main_type,subtype_code
编辑2:要深入分析我尝试SHOW CREATE TABLE {{table name}},结果如下.
axnmrs_cases:
CREATE TABLE `axnmrs_cases` (
`axrmrs_id` int(11) NOT NULL DEFAULT '0',
`case_id` int(11) NOT NULL DEFAULT '0',
`axncase_guid` varchar(100) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`date_created` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`datasource` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`claimnumber` varchar(60) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`platenumber` varchar(60) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`displayname` varchar(200) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`vin` varchar(40) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`lastcalc_manufacturer_code` varchar(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`lastcalc_model_code` varchar(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`lastcalc_submodel_code` varchar(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`lastcalc_model_options` varchar(500) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`audavin_triggered` varchar(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`vehicletype` varchar(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`accident_date` timestamp NULL DEFAULT '0000-00-00 00:00:00',
`date_closed` timestamp NULL DEFAULT '0000-00-00 00:00:00',
`claimowner_memberid` varchar(200) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`repairer_memberid` varchar(200) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`insurer_memberid` varchar(200) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`assessor_memberid` varchar(200) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`accidentcause_code` int(11) DEFAULT NULL,
`casetype_code` int(11) DEFAULT NULL,
`claimtype_code` int(11) DEFAULT NULL,
`damagecause_code` int(11) DEFAULT NULL,
`damagearea_codes` varchar(20) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`totalloss` varchar(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`inspectionrequired` varchar(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`manufacturing_year` int(11) NOT NULL DEFAULT '0',
`registration_date` timestamp NULL DEFAULT '0000-00-00 00:00:00',
`mileage` int(11) NOT NULL DEFAULT '0',
`country` varchar(2) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
KEY `VIN_index` (`vin`)
) ENGINE=InnoDB AUTO_INCREMENT=3471525 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Run Code Online (Sandbox Code Playgroud)
axnmrs_calculations:
CREATE TABLE `axnmrs_calculations` (
`calculation_id` int(11) NOT NULL,
`case_id` int(11) NOT NULL,
`guid` varchar(50) NOT NULL,
`calculationdate` varchar(50) NOT NULL,
`name` varchar(50) NOT NULL,
`calsscalnr` varchar(50) NOT NULL,
`model_options` varchar(60) NOT NULL,
`spareparts` varchar(60) NOT NULL,
`laborcosts` varchar(60) NOT NULL,
`paintlabor` varchar(60) NOT NULL,
`paintmaterial` varchar(40) NOT NULL,
`extracosts` varchar(60) NOT NULL,
`environmentalcosts` varchar(60) NOT NULL,
`totalcosts` varchar(60) NOT NULL,
`totalvat` varchar(60) NOT NULL,
`laborhours` varchar(60) NOT NULL,
`painthours` varchar(60) NOT NULL,
`totaldeduction` varchar(60) NOT NULL,
`partsadjustment` varchar(60) NOT NULL,
`calculationtype` varchar(60) NOT NULL,
`license` varchar(60) NOT NULL,
`memberrole` varchar(60) NOT NULL,
`currency` varchar(5) NOT NULL,
`country` varchar(2) NOT NULL,
KEY `caseid_index` (`case_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)
axnmrs_positions:
CREATE TABLE `axnmrs_positions` (
`calculation_id` int(11) NOT NULL DEFAULT '0',
`case_id` int(11) NOT NULL DEFAULT '0',
`position_id` int(11) NOT NULL DEFAULT '0',
`blockline` varchar(7) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`repairmethod` varchar(3) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`guidenumber` varchar(4) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`amount` float NOT NULL DEFAULT '0',
`hours` float NOT NULL DEFAULT '0',
`starmutation` varchar(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`text` varchar(200) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`originalpartnumber` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`originalpartprice` float NOT NULL DEFAULT '0',
`manufacturercode` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`quality` varchar(5) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`suppliercode` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
KEY `calculationid_index` (`calculation_id`),
KEY `repairmethod` (`repairmethod`),
KEY `caseid_index` (`case_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Run Code Online (Sandbox Code Playgroud)
car_type:
CREATE TABLE `car_type` (
`manufacturer_code` varchar(2) NOT NULL,
`main_type` varchar(2) NOT NULL,
`subtype_code` varchar(2) NOT NULL,
`manufacturer` varchar(100) NOT NULL,
`model` varchar(20) CHARACTER SET utf8 COLLATE utf8_czech_ci NOT NULL,
`submodel` varchar(20) CHARACTER SET utf8 COLLATE utf8_czech_ci NOT NULL,
KEY `manufacturer_code` (`manufacturer_code`),
KEY `main_type` (`main_type`),
KEY `subtype_code` (`subtype_code`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)
organization_list:
CREATE TABLE `organization_list` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`memberId` varchar(99) NOT NULL,
`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_czech_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `memberId` (`memberId`)
) ENGINE=InnoDB AUTO_INCREMENT=133 DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)
该配置文件为您提供了答案 - 查询缓存.
从只有0.2的查询中获取结果的唯一方法是它来自"查询缓存".这是选择结果集的哈希.你显然运行了两次查询,这是第二次计时.再试一次,SELECT SQL_NO_CACHE ...看看它"真正"需要多长时间.
请注意,"查询缓存"不是MySQL使用的唯一"缓存"; 所以在使用术语时要小心.
(那不是10倍;那要长10000倍.)
除此之外,你的下一个问题是为什么这样的查询需要2.4秒? 这是你应该解决的问题.线索在EXPLAIN- 首先注意到巨大的"行" car.
LEFT JOIN car_type as car
on car.manufacturer_code = c.lastcalc_manufacturer_code
AND car.main_type = c.lastcalc_model_code
AND car.subtype_code = c.lastcalc_submodel_code
Run Code Online (Sandbox Code Playgroud)
添加此复合索引car_type将加速查询的该部分.
INDEX(manufacturer_code, main_type, subtype_code)
Run Code Online (Sandbox Code Playgroud)
(在这种情况下,顺序无关紧要.)
也,
LEFT JOIN organization_list as org on org.memberId = c.insurer_memberid
Run Code Online (Sandbox Code Playgroud)
需要一个一致的memberId定义.仔细看看CHARACTER SET两张表中的内容.
使用ALTER TABLE ... CONVERT TO ...来解决这个问题,以便它可以使用索引.