I am trying to optimize this query as good as possible,but still i am getting query locks due to this query.Can any one provide some suggestions in improving it.The query fetches the last one day entries from the table.
The QUERY:
SELECT CR.id,
CR.servicecode,
CR.leadtime,
CR.redirecturl,
CRE.custemail,
CRE.custlname,
CRE.custfname,
CRE.duration,
CR.userid,
AA.lpintrotimearr,
AA.lpintrotimedep,
AA.landdatetimearr,
AA.landdatetimedep,
CR.newcustid,
cre.CRE.custmobilephone,
CRE.brandname
FROM response CR
LEFT JOIN agreement AA
ON CR.id = AA.id
LEFT JOIN request CRE
ON CRE.id = CR.id
WHERE CR.id > '20120617145243'
AND CR.approved = 1
AND CR.chlapproved != 0
AND CR.chlapproved IS NOT NULL
AND AA.id IS NOT NULL
AND ( AA.stdsign != 'on'
OR AA.stdsign IS NULL )
AND ( AA.ivaflag = 0
OR AA.ivaflag IS NULL )
AND ( AA.opt IS NULL
OR AA.opt = 0 );
The EXPLAIN:

One way is to index all 3(AA.stdsign,AA.ivaflag and AA.opts) columns but all the three flags (AA.stdsign,AA.ivaflag and AA.opts) can have only 3 different values.Will indexing these reduce query run time?
All the ids are of varchar(60) data type.
There isn’t much to be improved on the query itself.
On the other hand, setting an index on
AA.stdsign,AA.ivaflagandAA.optsshould help a lot.As your
EXPLAINindicates, no suitable key is found for yourAAtable and all 534956 rows must be scanned to satisfy theWHEREclause.[edit]
One last tip: using large column types (such as
VARCHAR(60)) for your primary keys is probably sub-optimal.First reason: every time you need to reference a row (e.g. in a foreign key), you need another
VARCHAR(60).Second reason: comparisons on strings are slower than on integers (hence it may render a
JOINslower than necessary)You may want to add an
INTcolumn to your tables, and use it as primary key.