This is my first time posting here. I am new to MySQL and trying to learn it as fast as possible but this issue is causing a problem to production and need to reach out for help.
This server is running Suse linux and has a MariaDB 5.5.46. We have been having a huge spike in threads on this active server and I have been digging into this for a little while. I have used Jet Profiler to get a more visual idea of what is going on while looking into this matter and a few days ago I saw this spike live on the server shooting up to 600 threads for about 2 minutes. Thanks to that i have isolated a query that even in the CLI is taking 45 to 57 sec to complete.
This is the offending query that i have pulled out of the Jet Profiler. it is coming from a web site pulling a list off the source for an external person to view the contents. The active server that it is pulling from is phone system.
SELECT CONCAT( DATE(call_date),'<br/>', TIME(call_date) ) as DateTime
, vlog.campaign_id AS Campaign
, CONCAT(emp.full_name,' [',vlog.user,']') AS 'Rep'
, CONCAT(lead.first_name,' ',lead.last_name) as 'Name'
, CONCAT(lead.state,'/',lead.city) AS 'State-City' , lead.lead_id
, vlog.status as CallSts
, lead.status as LeadSts
, vlog.phone_number AS 'Phone'
, timediff(end_time,start_time) as 'Length'
, location
FROM
vicidial_log as vlog
LEFT JOIN recording_log as rlog ON vlog.uniqueid = rlog.vicidial_id
LEFT JOIN vicidial_list as lead ON vlog.lead_id = lead.lead_id
LEFT JOIN vicidial_users as emp ON emp.user = rlog.user
WHERE
date(vlog.call_date) <= '2016-03-11'
AND vlog.status <> 'INCALL'
AND vlog.length_in_sec > 10
AND vlog.campaign_id like 'AG%'
AND location IS NOT NULL
AND rlog.end_time IS NOT NULL
Here is the EXPLAIN addition.
+----+-------------+-------+--------+----------------------+-------------+---------+---------------------------+---------+---------------------------------------------------------------------+ | ID | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+----------------------+-------------+---------+---------------------------+---------+---------------------------------------------------------------------+ | 1 | SIMPLE | rlog | range | filename,vicidial_id | vicidial_id | 63 | NULL | 1040870 | Using index condition; Using where; Using temporary; Using filesort | | 1 | SIMPLE | vlog | eq_ref | PRIMARY | PRIMARY | 62 | asterisk.rlog.vicidial_id | 1 | Using where | | 1 | SIMPLE | lead | eq_ref | PRIMARY | PRIMARY | 4 | asterisk.vlog.lead_id | 1 | | | 1 | SIMPLE | emp | eq_ref | user | user | 62 | asterisk.rlog.user | 1 | Using where | +----+-------------+-------+--------+----------------------+-------------+---------+---------------------------+---------+---------------------------------------------------------------------+
Best Answer
It looks like indexes are not properly used.
You have 6
WHERE
(AND
) clauses, each of them should be analyzed from an index selection perspective :clause 1:
DATE(vlog.call_date) <= '2016-03-11'
This one won't be a good candidate because:
call_date
with aDATE()
function, making any index on this column totally unusable.call_date
lower than a recent date would not filter a lot of records anyway since most of the calls would likely be in the rangeclause 2:
vlog.status <> 'INCALL'
A not equal clause won't be able to use any
status
based index as far as I can tell.clause 3:
vlog.length_in_sec > 10
I can imagine most of the calls would last more than 10s, so an numerical index based on this column would probably not filter many records, if ever defined. May depend on actual recorded data though.
clause 4:
vlog.campaign_id like 'AG%'
I like this one. A string based index would filter on the compaigns stating with these two characters. If text were equally distributed upon alphabetical letters — LIKE clause being case insensitive — you would have a 26x26=612 factor filter. It's less probable, but I would at least say a 100 factor, which is kind of a good start.
You'd still have to add the index on that column if not existing, and also make sure you would launch the query with at least 2 letters, to be efficient.
clause 5:
location IS NOT NULL
Nullable columns can be indexed and filtered on null values, but they are arguably very common values that would not filter a lot of records. I would preferably follow the clause 4 lead.
clause 6:
rlog.end_time IS NOT NULL
Same as clause 5.
To summarize, I would add an index on
compaign_id
and see what happens.Hope that helps.