【发布时间】:2022-01-24 23:58:08
【问题描述】:
我有一件很奇怪的事情。 具有完全相同配置的两台服务器为相同的查询(巨大的查询)提供了 2 种不同的性能。 On是700ms,另一个是10sec!
问题在于“在 sd.shyft_id = shyfts.id 上左连接 shyfts_detail sd”,在一台服务器上它使用密钥 'shyft_id' (-> 第 1 行),而在慢速服务器上它不使用密钥并且行是+1985651(大!)
如何强制按键?
explain select
s.department_id, d.account_id, s.id as id, s.shyft_id as parentShift, 'CLOCKIN' as shyftType, s.ressource_record_id,
rpg.user_type,
if(
(select count(*) from hr_partners_account where account_id=s.account_id and active=1)>1,
rpg.hr_partner,
(select hr_partner_id from hr_partners_account where account_id=s.account_id and active=1 limit 1)
) as hr_partner,
rpg.worktime_calculation_method as user_worktime_calculation_method,
(select worktime_calculation_method from user_category where id=rpg.user_type) as status_worktime_calculation_method,
rpg.hr_partner as hr_partner_user,
WEEKDAY(s.startdate) + 1 as dayNumber,
WEEK(s.startdate,1) as weekNumber,
DATE_FORMAT(s.startdate,'%d') as day,
DATE_FORMAT(s.startdate,'%m') as month,
YEAR(s.startdate) as year,
s.startdate as start,
DATE_FORMAT(s.startdate, '%Y-%m-%d') as startDate,
DATE_FORMAT(s.startdate, '%H:%i') as startHour,
s.enddate as end,
DATE_FORMAT(s.enddate, '%Y-%m-%d') as endDate,
DATE_FORMAT(s.enddate, '%H:%i') as endHour,
if(dpc.paid_clockin_break=1,
(SELECT SUM(IFNULL(TIMESTAMPDIFF(MINUTE, shyfts_clockin_breaks.startdate, shyfts_clockin_breaks.enddate),0)) FROM
shyfts_clockin_breaks WHERE clockin_id=s.id),
'0'
) AS pause_paid,
if(dpc.paid_clockin_break=1,
'0',
(SELECT SUM(IFNULL(TIMESTAMPDIFF(MINUTE, shyfts_clockin_breaks.startdate, shyfts_clockin_breaks.enddate),0)) FROM
shyfts_clockin_breaks WHERE clockin_id=s.id)
) AS pause_unpaid,
sum(TIME_TO_SEC(TIMEDIFF(s.enddate, s.startdate)))/60 as totalWork,
if((SELECT SUM(IFNULL(TIMESTAMPDIFF(MINUTE, shyfts_clockin_breaks.startdate, shyfts_clockin_breaks.enddate),0)) FROM
shyfts_clockin_breaks WHERE clockin_id=s.id)>0
AND dpc.paid_clockin_break=0
,(sum(TIME_TO_SEC(TIMEDIFF(s.enddate, s.startdate)))/60)-(SELECT SUM(IFNULL(TIMESTAMPDIFF(MINUTE,
shyfts_clockin_breaks.startdate, shyfts_clockin_breaks.enddate),0)) FROM shyfts_clockin_breaks WHERE clockin_id=s.id)
,sum(TIME_TO_SEC(TIMEDIFF(s.enddate, s.startdate)))/60) as worktime,
s.skill as skills,
s.section,
(SELECT GROUP_CONCAT(DISTINCT attribute_id ORDER BY attribute_id DESC) FROM shyfts_clockin_attributes where
shyfts_clockin_attributes.clockin_id=s.id) as attributes,
1 as 'shyft_type',
0 as 'dayoffId',
0 as 'hrRealCode',
0 as 'hr_code',
0 as 'dayoff_name',
0 as 'shortcode',
0 as 'hr_shortcode',
0 as 'dayoff_recup',
0 as 'dayoff_vacation',
0 as dayoff_paid,
0 as dayoff_fullday,
d.country,
(select count(*) from publicholidays ph where ph.fulldate = DATE_FORMAT(s.startdate, '%Y-%m-%d') and ph.active=1 and
ph.country=d.country) as public_holiday,
rpg.hr_max_hours_year, rpg.hr_max_hours_week,
(select hours_week from contracts where contracts.ressource_record_id=s.ressource_record_id and
contracts.department_id=s.department_id and (contracts.enddate>=s.startdate or contracts.enddate is null) and
contracts.active=1 and contracts.archived=0 group by contracts.ressource_record_id order by id) as contract_hours_week,
(select days_week from contracts where contracts.ressource_record_id=s.ressource_record_id and
contracts.department_id=s.department_id and (contracts.enddate>=s.startdate or contracts.enddate is null) and
contracts.active=1 and contracts.archived=0 group by contracts.ressource_record_id order by id) as contract_days_week,
rpg.hr_max_hours_month, rpg.hr_max_hours_trimester, rpg.hr_hours_week,
rpg.hr_days_week, rpg.hr_low_flexibility, rpg.hr_high_flexibility,
rpg.hr_dayoff_year, rpg.lang, i18n.shortcode as languageCode,
dpg.default_fulldayhours,
sections.section_name as section_name
from shyfts_clockin s
left join department_params_general dpg on dpg.id = s.department_id
left join ressources_params_general rpg on rpg.ressource_record_id = s.ressource_record_id and
rpg.department_id=s.department_id
left join department d on d.id = s.department_id
left join department_params_clockin dpc on dpc.department_id = s.department_id
left join i18n_language i18n on i18n.id=d.lang
left join sections on sections.id=s.section
where
((s.shyft_id<>'' and s.active=1) or (s.shyft_id='' and s.active=1 and s.freeshift_approved=1))
and s.startdate>="2022-01-01 00:00:00" and s.startdate
<"2022-01-31 23:59:59" and s.department_id=1439
group by s.id
UNION
select
shyfts.department_id, shyfts.account_id, shyfts.id as id, 0 as parentShift, 'PLANNED' as shyftType, shyfts.ressource_record_id, rpg.user_type,
if(
(select count(*) from hr_partners_account where account_id=shyfts.account_id and active=1)>1,
rpg.hr_partner,
(select hr_partner_id from hr_partners_account where account_id=shyfts.account_id and active=1 limit 1)
) as hr_partner,
rpg.worktime_calculation_method as user_worktime_calculation_method,
(select worktime_calculation_method from user_category where id=rpg.user_type) as status_worktime_calculation_method,
rpg.hr_partner as hr_partner_user,
WEEKDAY(shyfts.startdate) + 1 as dayNumber,
WEEK(shyfts.startdate,1) as weekNumber,
DATE_FORMAT(shyfts.startdate,'%d') as day,
DATE_FORMAT(shyfts.startdate,'%m') as month,
YEAR(shyfts.startdate) as year,
shyfts.startdate as start,
DATE_FORMAT(shyfts.startdate, '%Y-%m-%d') as startDate,
DATE_FORMAT(shyfts.startdate, '%H:%i') as startHour,
shyfts.enddate as end,
DATE_FORMAT(shyfts.enddate, '%Y-%m-%d') as endDate,
DATE_FORMAT(shyfts.enddate, '%H:%i') as endHour,
(SELECT SUM(IFNULL(duration,0)) FROM shyfts_pause WHERE shyft_id=shyfts.id and paid=1) AS pause_paid,
(SELECT SUM(IFNULL(duration,0)) FROM shyfts_pause WHERE shyft_id=shyfts.id and paid=0) AS pause_unpaid,
(TIME_TO_SEC(TIMEDIFF(shyfts.enddate, shyfts.startdate)))/60 as totalWork,
if((SELECT SUM(IFNULL(duration,0)) FROM shyfts_pause WHERE shyft_id=shyfts.id and paid=0)>0,
(sum(TIME_TO_SEC(TIMEDIFF(shyfts.enddate, shyfts.startdate)))/60)-(SELECT SUM(IFNULL(duration,0)) FROM shyfts_pause WHERE shyft_id=shyfts.id and paid=0),
(TIME_TO_SEC(TIMEDIFF(shyfts.enddate, shyfts.startdate)))/60
) as worktime,
(SELECT GROUP_CONCAT(DISTINCT skill_id ORDER BY skill_id DESC) FROM shyfts_skills where shyfts_skills.shyft_id=shyfts.id) as skills,
shyfts.section,
(SELECT GROUP_CONCAT(DISTINCT attribute_id ORDER BY attribute_id DESC) FROM shyfts_attributes where shyfts_attributes.shyft_id=shyfts.id) as attributes,
sd.shyft_type,
sdo.dayoff_type as dayoffId,
(select code from hr_timesheet_code where id=hcm2.hr_code_id limit 1) as hr_global_code,
htc.code as hr_code,
dayoff.name AS dayoff_name,
dayoff.shortcode AS shortcode,
if(d.lang=2, htc.shortcode_nl, htc.shortcode_fr) as hr_shortcode,
dayoff.recup AS dayoff_recup,
dayoff.real_dayoff AS dayoff_vacation,
sdo.paid as dayoff_paid,
sdo.fullday as dayoff_fullday,
d.country,
(select count(*) from publicholidays ph where ph.fulldate = DATE_FORMAT(shyfts.startdate, '%Y-%m-%d') and ph.active=1 and ph.country=d.country) as public_holiday,
rpg.hr_max_hours_year, rpg.hr_max_hours_week,
(select hours_week from contracts where contracts.ressource_record_id=shyfts.ressource_record_id and contracts.department_id=shyfts.department_id and (contracts.enddate>=shyfts.startdate or contracts.enddate is null) and contracts.active=1 and contracts.archived=0 group by contracts.ressource_record_id order by id) as contract_hours_week,
(select days_week from contracts where contracts.ressource_record_id=shyfts.ressource_record_id and contracts.department_id=shyfts.department_id and (contracts.enddate>=shyfts.startdate or contracts.enddate is null) and contracts.active=1 and contracts.archived=0 group by contracts.ressource_record_id order by id) as contract_days_week,
rpg.hr_max_hours_month,
rpg.hr_max_hours_trimester, rpg.hr_hours_week,
rpg.hr_days_week, rpg.hr_low_flexibility, rpg.hr_high_flexibility,
rpg.hr_dayoff_year, rpg.lang, i18n.shortcode as languageCode,
dpg.default_fulldayhours,
sections.section_name as section_name
from shyfts
left join ressources_params_general rpg on rpg.ressource_record_id = shyfts.ressource_record_id and rpg.department_id=shyfts.department_id
left join shyfts_dayoff sdo on sdo.shyft_id = shyfts.id
left join shyfts_detail sd on sd.shyft_id = shyfts.id
left join dayoff on dayoff.id = sdo.dayoff_type
left join department d on d.id = shyfts.department_id
left join hr_codes_mapping hcm on hcm.dayoff_id=sdo.dayoff_type and hcm.account_id=d.account_id and hcm.active=1 and hcm.hr_partner_id=rpg.hr_partner
left join hr_codes_mapping hcm2 on hcm2.dayoff_id=sdo.dayoff_type and hcm2.account_id=d.account_id and hcm2.active=1 and hcm2.hr_partner_id=(select hr_partner_id from hr_partners_account where account_id=shyfts.account_id and active=1 limit 1)
left join hr_timesheet_code htc on htc.id=hcm.hr_code_id
left join department_params_general dpg on dpg.department_id = shyfts.department_id
left join i18n_language i18n on i18n.id=d.lang
left join sections on sections.id=shyfts.section
where shyfts.active=1 and shyfts.approved=1 and shyfts.ressource_record_id>0 and shyfts.startdate>="2022-01-01 00:00:00" and shyfts.startdate<"2022-01-31 23:59:59" and shyfts.department_id=1439 and (sd.shyft_type=1 or sd.shyft_type=2)
group by shyfts.id
order by ressource_record_id, startdate, enddate, department_id
【问题讨论】:
-
要使用索引提示,您需要知道 sd.shyft_id 的索引名称;最简单的查看方法是
show create table shyfts_detail;