简体   繁体   中英

slow mysql query when using concat and filesort

All the queries on this system are fast except if I add 'Recent Status' and/or 'Recent Status (Extended)' to my search.

Candidates Page with Re4cent Status selected

The query from slow log.

SELECT SQL_CALC_FOUND_ROWS
candidate.candidate_id AS candidateID,
candidate.candidate_id AS exportID,
candidate.is_hot AS isHot,
candidate.date_modified AS dateModifiedSort,
candidate.date_created AS dateCreatedSort,
IF(candidate_joborder_submitted.candidate_joborder_id, 1, 0) AS submitted,
IF(attachment_id, 1, 0) AS attachmentPresent,
candidate.first_name AS firstName,
candidate.last_name AS lastName,
candidate.city AS city,
candidate.state AS state,
candidate.key_skills AS keySkills,
owner_user.first_name AS ownerFirstName,owner_user.last_name AS ownerLastName,CONCAT(owner_user.last_name, owner_user.first_name) AS ownerSort,
DATE_FORMAT(candidate.date_created, '%m-%d-%y') AS dateCreated,
DATE_FORMAT(candidate.date_modified, '%m-%d-%y') AS dateModified,
(
SELECT
CONCAT(
'<a href="index.php?m=joborders&amp;a=show&amp;jobOrderID=',
joborder.joborder_id,
'" title="',
joborder.title,
' (',
company.name,
')">',
candidate_joborder_status.short_description,
'</a>'
)
FROM
candidate_joborder
LEFT JOIN candidate_joborder_status
ON candidate_joborder_status.candidate_joborder_status_id = candidate_joborder.status
LEFT JOIN joborder
ON joborder.joborder_id = candidate_joborder.joborder_id
LEFT JOIN company
ON joborder.company_id = company.company_id
WHERE
candidate_joborder.candidate_id = candidate.candidate_id
ORDER BY
candidate_joborder.date_modified DESC
LIMIT 1
) AS lastStatus
FROM
candidate
LEFT JOIN attachment
ON candidate.candidate_id = attachment.data_item_id
AND attachment.data_item_type = 100
LEFT JOIN candidate_joborder AS candidate_joborder_submitted
ON candidate_joborder_submitted.candidate_id = candidate.candidate_id
AND candidate_joborder_submitted.status >= 400
AND candidate_joborder_submitted.site_id = 1
AND candidate_joborder_submitted.status != 650
LEFT JOIN user AS owner_user ON candidate.owner = owner_user.user_id LEFT JOIN saved_list_entry
ON saved_list_entry.data_item_type = 100
AND saved_list_entry.data_item_id = candidate.candidate_id
AND saved_list_entry.site_id = 1
WHERE
candidate.site_id = 1

GROUP BY candidate.candidate_id

ORDER BY dateModifiedSort DESC
LIMIT 0, 15;

EXPLAIN RESULTS

'1', 'PRIMARY', 'attachment', 'system', 'IDX_type_id,IDX_data_item_id,dataitem1', NULL, NULL, NULL, '0', 'const row not found'
'1', 'PRIMARY', 'candidate', 'ALL', 'IDX_site_first_last_modified,IDX_site_id_email_1_2', NULL, NULL, NULL, '8645', 'Using where; Using temporary; Using filesort'
'1', 'PRIMARY', 'candidate_joborder_submitted', 'ref', 'IDX_candidate_id,IDX_site_id,IDX_status_special,IDX_site_joborder', 'IDX_candidate_id', '4', 'opencats.candidate.candidate_id', '1', 'Using where'
'1', 'PRIMARY', 'owner_user', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'opencats.candidate.owner', '1', 'Using where'
'1', 'PRIMARY', 'saved_list_entry', 'ref', 'IDX_data_item_type,IDX_data_item_id,IDX_type_id', 'IDX_data_item_id', '4', 'opencats.candidate.candidate_id', '1', 'Using where'
'2', 'DEPENDENT SUBQUERY', 'candidate_joborder', 'index', 'IDX_candidate_id', 'IDX_date_modified', '8', NULL, '1', 'Using where'
'2', 'DEPENDENT SUBQUERY', 'candidate_joborder_status', 'eq_ref', 'PRIMARY,status1', 'PRIMARY', '4', 'opencats.candidate_joborder.status', '1', ''
'2', 'DEPENDENT SUBQUERY', 'joborder', 'eq_ref', 'PRIMARY,order1', 'PRIMARY', '4', 'opencats.candidate_joborder.joborder_id', '1', ''
'2', 'DEPENDENT SUBQUERY', 'company', 'eq_ref', 'PRIMARY,company1,comp1', 'PRIMARY', '4', 'opencats.joborder.company_id', '1', 'Using where'

What I believe is the slow part.

SELECT CONCAT(
'<a href="index.php?m=joborders&amp;a=show&amp;jobOrderID=',
joborder.joborder_id,
'" title="',
joborder.title,
' (',
company.name,
')">',
candidate_joborder_status.short_description,
'</a>'
)
FROM
candidate_joborder
LEFT JOIN candidate_joborder_status
ON candidate_joborder_status.candidate_joborder_status_id = candidate_joborder.status
LEFT JOIN joborder
ON joborder.joborder_id = candidate_joborder.joborder_id
LEFT JOIN company
ON joborder.company_id = company.company_id
WHERE
candidate_joborder.candidate_id = candidate.candidate_id
ORDER BY
candidate_joborder.date_modified DESC
LIMIT 1
) AS lastStatus

My questions is 'what course of action I can take to speed this query up'? There are only 8000 rows on the database and plenty of server resources. The tables are MyISAM and I have tried adding indexes which you can see some being used in the explain however I don't think indexes are really going to help much because it appears what is making this slow is concat, filesort,temp table (with no indexes) and possibly the triple join.

This is my first post so please excuse the formatting. I will try and edit it after i post and see how it looks.

Thank you

You could index the temporary table as well, it may improve performance, and try to avoid file sorting whenever you can. Another resource to help you is the procedure_analyse option. It will help you create appropriate variable types.

Find more information here: https://dev.mysql.com/doc/refman/5.7/en/procedure-analyse.html

Thank you for the information, I installed mariadb 10.1 and its all good now. It was on 5.5 centos7

SELECT  CONCAT( '<a href="index.php?m=joborders&amp;a=show&amp;jobOrderID=',
                j.joborder_id, '" title="', j.title, 
                ' (', co.name, ')">',
                cjs.short_description, '</a>' 
              )
    FROM  candidate_joborder AS cj
    LEFT JOIN  candidate_joborder_status AS cjs
          ON cjs.candidate_joborder_status_id = cj.status
    LEFT JOIN  joborder AS j
          ON j.joborder_id = cj.joborder_id
    LEFT JOIN  company AS co
          ON j.company_id = co.company_id
    WHERE  cj.candidate_id = c.candidate_id
    ORDER BY  cj.date_modified DESC
    LIMIT  1 

cj needs INDEX(candidate_id, date_modified)

    WHERE  candidate.site_id = 1
    GROUP BY  candidate.candidate_id
    ORDER BY  dateModifiedSort DESC

candidate needs INDEX(site_id, candidate_id)

Note: INDEX(a,b) is not the same as INDEX(a), INDEX(b) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM