[mythtv-commits] Ticket #2014: excessive sql query for listing previously recorded programs

MythTV mythtv at cvs.mythtv.org
Mon Jul 3 16:34:30 UTC 2006


#2014: excessive sql query for listing previously recorded programs
-----------------------+----------------------------------------------------
 Reporter:  oa at iki.fi  |       Owner:  ijr 
     Type:  defect     |      Status:  new 
 Priority:  minor      |   Milestone:      
Component:  mythtv     |     Version:  0.19
 Severity:  medium     |  
-----------------------+----------------------------------------------------
 My backend/frontend combo machine needs 15 seconds to respond on every
 switch to "watch recordings" screen or mythweb's recorded programs page.
 The reason for this is the query to MySQL, below:

 SELECT DISTINCT channel.chanid, channel.sourceid, program.starttime,
 program.endtime, program.title, program.subtitle, program.description,
 channel.channum, channel.callsign, channel.name, oldrecorded.endtime IS
 NOT NULL AS oldrecduplicate, program.category, record.recpriority,
 record.dupin, recorded.endtime IS NOT NULL AS recduplicate, oldfind.findid
 IS NOT NULL AS findduplicate, record.type, record.recordid,
 program.starttime - INTERVAL record.startoffset minute AS recstartts,
 program.endtime + INTERVAL record.endoffset minute AS recendts,
 program.previouslyshown, record.recgroup, record.dupmethod,
 channel.commfree, capturecard.cardid, cardinput.cardinputid,
 UPPER(cardinput.shareable) = 'Y' AS shareable, program.seriesid,
 program.programid, program.category_type, program.airdate, program.stars,
 program.originalairdate, record.inactive, record.parentid, (CASE
 record.type   WHEN 6    THEN record.findid   WHEN 9    THEN
 to_days(date_sub(program.starttime, interval
 time_format(record.findtime, '%H:%i') hour_minute))   WHEN 10    THEN
 floor((to_days(date_sub(program.starttime, interval
 time_format(record.findtime, '%H:%i') hour_minute)) -
 record.findday)/7) * 7 + record.findday   WHEN 7    THEN record.findid
 ELSE 0  END) , record.playgroup, oldrecstatus.recstatus,
 oldrecstatus.reactivate, channel.recpriority + cardinput.preference FROM
 recordmatch  INNER JOIN record ON (recordmatch.recordid = record.recordid)
 INNER JOIN program ON (recordmatch.chanid = program.chanid AND
 recordmatch.starttime = program.starttime AND
 recordmatch.manualid = program.manualid)  INNER JOIN channel ON
 (channel.chanid = program.chanid)  INNER JOIN cardinput ON
 (channel.sourceid = cardinput.sourceid)  INNER JOIN capturecard ON
 (capturecard.cardid = cardinput.cardid)  LEFT JOIN oldrecorded as
 oldrecstatus ON   ( oldrecstatus.station = channel.callsign AND
 oldrecstatus.starttime = program.starttime AND     oldrecstatus.title =
 program.title )  LEFT JOIN oldrecorded ON   (     record.dupmethod > 1 AND
 oldrecorded.duplicate <> 0 AND     program.title = oldrecorded.title
 AND      (       (program.programid <> '' AND program.generic = 0
 AND program.programid = oldrecorded.programid)       OR
 (oldrecorded.findid <> 0 AND         oldrecorded.findid = (CASE
 record.type   WHEN 6    THEN record.findid   WHEN 9    THEN
 to_days(date_sub(program.starttime, interval
 time_format(record.findtime, '%H:%i') hour_minute))   WHEN 10    THEN
 floor((to_days(date_sub(program.starttime, interval
 time_format(record.findtime, '%H:%i') hour_minute)) -
 record.findday)/7) * 7 + record.findday   WHEN 7    THEN record.findid
 ELSE 0  END) )       OR       (        program.generic = 0        AND
 (program.programid = '' OR oldrecorded.programid = '')        AND
 (((record.dupmethod & 0x02) = 0) OR (program.subtitle <> ''           AND
 program.subtitle = oldrecorded.subtitle))        AND
 (((record.dupmethod & 0x04) = 0) OR (program.description <> ''
 AND program.description = oldrecorded.description))       )      )   )
 LEFT JOIN recorded ON   (     record.dupmethod > 1 AND
 recorded.duplicate <> 0 AND     program.title = recorded.title AND
 recorded.recgroup <> 'LiveTV'      AND      (       (program.programid <>
 '' AND program.generic = 0        AND program.programid =
 recorded.programid)       OR       (recorded.findid <> 0 AND
 recorded.findid = (CASE record.type   WHEN 6    THEN record.findid   WHEN
 9    THEN to_days(date_sub(program.starttime, interval
 time_format(record.findtime, '%H:%i') hour_minute))   WHEN 10    THEN
 floor((to_days(date_sub(program.starttime, interval
 time_format(record.findtime, '%H:%i') hour_minute)) -
 record.findday)/7) * 7 + record.findday   WHEN 7    THEN record.findid
 ELSE 0  END) )       OR       (        program.generic = 0        AND
 (program.programid = '' OR recorded.programid = '')        AND
 (((record.dupmethod & 0x02) = 0) OR (program.subtitle <> ''           AND
 program.subtitle = recorded.subtitle))        AND
 (((record.dupmethod & 0x04) = 0) OR (program.description <> ''
 AND program.description = recorded.description))       )      )   )  LEFT
 JOIN oldfind ON   (oldfind.recordid = recordmatch.recordid AND
 oldfind.findid = (CASE record.type   WHEN 6    THEN record.findid   WHEN 9
 THEN to_days(date_sub(program.starttime, interval
 time_format(record.findtime, '%H:%i') hour_minute))   WHEN 10    THEN
 floor((to_days(date_sub(program.starttime, interval
 time_format(record.findtime, '%H:%i') hour_minute)) -
 record.findday)/7) * 7 + record.findday   WHEN 7    THEN record.findid
 ELSE 0  END) )  ORDER BY record.recordid DESC

 It seems to me that a) that's pretty complex, b) it probably doesn't
 really need to fetch everything, and c) there's likely a join bug in there
 somewhere, because it returns "9972 rows in set (14.19 sec)", while the
 explain statement tells that the largest component table in that query is
 less than half that size:

 {{{+----+-------------+--------------+--------+----------------------+---------+---------+---------------------------------------------------------------------------------------------------+------+---------------------------------+
 | id | select_type | table        | type   | possible_keys        | key
 | key_len | ref
 | rows | Extra                           |
 +----+-------------+--------------+--------+----------------------+---------+---------+---------------------------------------------------------------------------------------------------+------+---------------------------------+
 |  1 | SIMPLE      | cardinput    | ALL    | NULL                 | NULL
 |    NULL | NULL
 |    2 | Using temporary; Using filesort |
 |  1 | SIMPLE      | capturecard  | eq_ref | PRIMARY              |
 PRIMARY |       4 | mythconverg.cardinput.cardid
 |    1 | Using index                     |
 |  1 | SIMPLE      | recordmatch  | ALL    | recordid             | NULL
 |    NULL | NULL
 | 5334 |                                 |
 |  1 | SIMPLE      | program      | eq_ref | PRIMARY,id_start_end |
 PRIMARY |      16 |
 mythconverg.recordmatch.chanid,mythconverg.recordmatch.starttime,mythconverg.recordmatch.manualid
 |    1 |                                 |
 |  1 | SIMPLE      | channel      | eq_ref | PRIMARY              |
 PRIMARY |       4 | mythconverg.program.chanid
 |    1 | Using where                     |
 |  1 | SIMPLE      | oldrecstatus | eq_ref | PRIMARY,title        |
 PRIMARY |     156 |
 mythconverg.channel.callsign,mythconverg.program.starttime,mythconverg.program.title
 |    1 |                                 |
 |  1 | SIMPLE      | record       | eq_ref | PRIMARY              |
 PRIMARY |       4 | mythconverg.recordmatch.recordid
 |    1 |                                 |
 |  1 | SIMPLE      | oldrecorded  | ref    | title,programid      | title
 |     128 | mythconverg.program.title
 |    6 |                                 |
 |  1 | SIMPLE      | recorded     | ref    | programid,title      | title
 |     128 | mythconverg.program.title
 |    1 |                                 |
 |  1 | SIMPLE      | oldfind      | eq_ref | PRIMARY              |
 PRIMARY |       8 | mythconverg.recordmatch.recordid,func
 |    1 | Using index                     |
 +----+-------------+--------------+--------+----------------------+---------+---------+---------------------------------------------------------------------------------------------------+------+---------------------------------+}}}

 My table is fully optimized (by a nightly backup + analyze job), so that
 query plan is pretty much the best job mysql 4.1.20 can do for the
 statement and schema.

 I tried to make sense of this query, but I can not even begin to figure
 out what it's supposed to do. Why does a query that presumably exists to
 list recorded programs try to eliminate duplicates from the schedule, for
 example?

-- 
Ticket URL: <http://cvs.mythtv.org/trac/ticket/2014>
MythTV <http://www.mythtv.org/>
MythTV


More information about the mythtv-commits mailing list