When I'm posting a question here I usually post a simplified abstraction.  This
time I have to post the full problem - and my problem is that my query takes
far too long to complete.  The query is quite speedy with very small data sets,
but it slows down unacceptably with data sets of any decent size.

Conceptually, here's what I'm trying to do: I've got a set of tasks to execute
("frames").  The frames which are ready to execute are in "wait" mode.  These
frames are associated with "layers" (in the table "layers"), and these layers
have 0 or more "layer resource requirements" (in the table "lrsrc").  I also
have a table of compute nodes ("nodes").  Each of these nodes has 0 or more
"node resources" (in the table "nrsrc").  If a layer requires "linux" and
"perl" resources, frames in that layer will only run on compute nodes which
have "linux" and "perl" resources.  This query is attempting to match a render
node named "foo" with a suitable frame for it to render.  In this data set I've
got 30 jobs, 434 layers, and 196036 frames of which 14309 are in "wait" mode.

This question is a followup to this thread, which helped me write the query:
http://lists.mysql.com/mysql/174017

Here's the query:

SELECT frames.id,frames.lid,frames.frame,frames.tile,layers.rsrcc,layers.layer
FROM nodes,frames,jobs,layers
LEFT JOIN lrsrc ON frames.id=lrsrc.id AND frames.lid=lrsrc.lid
LEFT JOIN nrsrc ON nodes.name=nrsrc.name AND nrsrc.rsrc=lrsrc.rsrc
WHERE frames.id=jobs.id
AND layers.id=frames.id
AND layers.lid=frames.lid
AND frames.state="wait"
AND (jobs.partition=nodes.partition OR nodes.partition IS NULL)
AND nodes.name="foo"
GROUP BY frames.id,frames.lid,frames.frame,frames.tile,nrsrc.name
HAVING layers.rsrcc=COUNT(nrsrc.rsrc)
LIMIT 1;

Here's the result:

+----+-----+-------+------+-------+----------------+
| id | lid | frame | tile | rsrcc | layer          |
+----+-----+-------+------+-------+----------------+
| 22 |   0 |     6 |    0 |     0 | unconventional |
+----+-----+-------+------+-------+----------------+
1 row in set (13.09 sec)

Here's the EXPLAIN:

+----+-------------+--------+--------+-------------------+---------+---------+--------------------------------------+-------+---------------------------------+
| id | select_type | table  | type   | possible_keys     | key     | key_len |
ref                                  | rows  | Extra                          
|
+----+-------------+--------+--------+-------------------+---------+---------+--------------------------------------+-------+---------------------------------+
|  1 | SIMPLE      | nrsrc  | system | PRIMARY,rsrc,name | NULL    |    NULL |
NULL                                 |     0 | const row not found            
|
|  1 | SIMPLE      | nodes  | const  | PRIMARY,partition | PRIMARY |      50 |
const                                |     1 | Using temporary; Using filesort
|
|  1 | SIMPLE      | frames | ref    | state,cid-id,id   | state   |       1 |
const                                | 16100 | Using where; Using index       
|
|  1 | SIMPLE      | jobs   | eq_ref | PRIMARY,partition | PRIMARY |       4 |
sherman.frames.id                    |     1 | Using where                    
|
|  1 | SIMPLE      | layers | eq_ref | PRIMARY           | PRIMARY |       5 |
sherman.frames.lid,sherman.frames.id |     1 |                                
|
|  1 | SIMPLE      | lrsrc  | index  | NULL              | rsrc    |      30 |
NULL                                 |   435 | Using index                    
|
+----+-------------+--------+--------+-------------------+---------+---------+--------------------------------------+-------+---------------------------------+

And here's the setup of my tables:

CREATE TABLE `nrsrc` (
  `name` varchar(15) NOT NULL default '',
  `rsrc` varchar(15) NOT NULL default '',
  PRIMARY KEY  (`rsrc`,`name`),
  KEY `rsrc` (`rsrc`),
  KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `nodes` (
  `name` varchar(50) NOT NULL default '',
  `ip` int(15) unsigned NOT NULL default '0',
  `state` enum('out','idle','busy','mia') NOT NULL default 'out',
  `partition` varchar(12) default NULL,
  `rsrcc` tinyint(4) unsigned NOT NULL default '0',
  `lastcontact` datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY  (`name`),
  KEY `partition` (`partition`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `frames` (
  `id` int(10) unsigned NOT NULL default '0',
  `lid` tinyint(3) unsigned NOT NULL default '0',
  `frame` smallint(5) unsigned NOT NULL default '0',
  `state` enum('depend','wait','run','fail','succeed') NOT NULL default
'depend',
  `tile` tinyint(3) unsigned NOT NULL default '0',
  `node` varchar(15) default NULL,
  PRIMARY KEY  (`tile`,`frame`,`lid`,`id`),
  KEY `state` (`state`),
  KEY `cid-id` (`lid`,`id`),
  KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `jobs` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `submit_time` timestamp NOT NULL default '0000-00-00 00:00:00',
  `name` varchar(25) NOT NULL default '',
  `logdir` varchar(50) default NULL,
  `owner` varchar(10) default NULL,
  `show` varchar(8) default NULL,
  `shot` varchar(8) default NULL,
  `partition` varchar(12) default NULL,
  `priority` float default NULL,
  `jobfile` varchar(80) default NULL,
  PRIMARY KEY  (`id`),
  KEY `name` (`name`),
  KEY `partition` (`partition`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `layers` (
  `id` int(10) unsigned NOT NULL default '0',
  `lid` tinyint(3) unsigned NOT NULL default '0',
  `order` tinyint(3) unsigned NOT NULL default '0',
  `layer` varchar(14) default NULL,
  `shell` varchar(30) default NULL,
  `script` text,
  `rsrcc` tinyint(4) unsigned NOT NULL default '0',
  PRIMARY KEY  (`lid`,`id`),
  KEY `order` (`order`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `lrsrc` (
  `id` int(10) unsigned NOT NULL default '0',
  `lid` tinyint(3) unsigned NOT NULL default '0',
  `rsrc` varchar(30) NOT NULL default '',
  PRIMARY KEY  (`rsrc`,`lid`,`id`),
  KEY `rsrc` (`rsrc`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- 
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]

Reply via email to