Jump to content

Slow query when order by is added, multiple inner joins..


BWorld

Recommended Posts

Hi All,

 

first of all I will introduce myself, my name is Chris Blokland and I am developing PHP for 4,5 years now.

I have knowledge of some other languages like C#, javascript, VB, ActionScript 3.0/Flex 3.5.

 

So to the point, I am having trouble with an mysql query wich I cant get solved some way..

 

The query is:

 

SELECT
    `s`.`id` AS s_id,
    `s`.`id_articles_categories` AS s_id_articles_categories,
    `s`.`id_security_boxes` AS s_id_security_boxes,
    `s`.`title` AS s_title,
    `s`.`author_name` AS s_author_name,
    `s`.`publish_date` AS s_publish_date,
    `s`.`tags` AS s_tags,
    `s`.`readCount` AS s_readCount,
    `s`.`id_articles_types` AS s_id_articles_types,
    `s`.`active` AS s_active,
    `s`.`declined` AS s_declined,
    `s`.`content` AS s_content,
    `s`.`date_creation` AS s_date_creation,
    `s`.`date_last_edit` AS s_date_last_edit,
    `u`.`id_security_boxes` AS u_id_security_boxes,
    `u`.`id_users_accounts` AS u_id_users_accounts,
    `u`.`id_security_groups` AS u_id_security_groups,
    `u`.`create` AS u_create,
    `u`.`read` AS u_read,
    `u`.`update` AS u_update,
    `u`.`delete` AS u_delete,
    `u`.`admin` AS u_admin,
    `t`.`id` AS t_id,
    `t`.`id_security_boxes` AS t_id_security_boxes,
    `t`.`id_security_control` AS t_id_security_control,
    `t`.`username` AS t_username,
    `t`.`password` AS t_password,
    `t`.`email` AS t_email,
    `t`.`activated` AS t_activated,
    `t`.`deleted` AS t_deleted,
    `t`.`signup_date` AS t_signup_date,
    `t`.`last_active` AS t_last_active,
    `t`.`last_location` AS t_last_location,
    `x`.`id` AS x_id,
    `x`.`id_security_boxes` AS x_id_security_boxes,
    `x`.`title` AS x_title,
    `x`.`article_class` AS x_article_class,
    `x`.`form_class` AS x_form_class,
    `y`.`id_security_boxes` AS y_id_security_boxes,
    `y`.`id_users_accounts` AS y_id_users_accounts,
    `y`.`id_security_groups` AS y_id_security_groups,
    `y`.`create` AS y_create,
    `y`.`read` AS y_read,
    `y`.`update` AS y_update,
    `y`.`delete` AS y_delete,
    `y`.`admin` AS y_admin
FROM
    articles_items s
            INNER JOIN
            (
              SELECT
                `acl`.`id_security_boxes` AS `id_security_boxes`,
                `acl`.`id_users_accounts` AS `id_users_accounts`,
                `acl`.`id_security_groups` AS `id_security_groups`,

                MAX(`acl`.`create`) AS `create`,
                  MAX(`acl`.`read`) AS `read`,
                MAX(`acl`.`update`) AS `update`,
                  MAX(`acl`.`delete`) AS `delete`,
                MAX(`acl`.`admin`) AS `admin`
              FROM
                  `security_acl` AS `acl`
              WHERE
                `acl`.`id_users_accounts` = 2 OR `acl`.`id_security_groups` IN (9,4,3,1)
              GROUP BY  `acl`.`id_security_boxes`
            ) AS `u`
INNER JOIN
    users_accounts t
ON
    t.id = s.id_users_accounts
INNER JOIN
    articles_types x
ON
    x.id = s.id_articles_types
            INNER JOIN
            (
              SELECT
                `acl`.`id_security_boxes` AS `id_security_boxes`,
                `acl`.`id_users_accounts` AS `id_users_accounts`,
                `acl`.`id_security_groups` AS `id_security_groups`,

                MAX(`acl`.`create`) AS `create`,
                  MAX(`acl`.`read`) AS `read`,
                MAX(`acl`.`update`) AS `update`,
                  MAX(`acl`.`delete`) AS `delete`,
                MAX(`acl`.`admin`) AS `admin`
              FROM
                  `security_acl` AS `acl`
              WHERE
                `acl`.`id_users_accounts` = 2 OR `acl`.`id_security_groups` IN (9,4,3,1)
              GROUP BY  `acl`.`id_security_boxes`
            ) AS `y`
WHERE
    s.active = 1
AND
    s.declined = 0
    AND
`u`.`id_security_boxes` = `s`.`id_security_boxes`
AND
    t.deleted = 0
AND
    t.activated = 1
    AND
`y`.`id_security_boxes` = `x`.`id_security_boxes`
ORDER BY
  s.publish_date DESC
LIMIT
    0,10

 

Well, this query is used for displaying a list of articles from a wiki-like system.

Ehm, the inner joins you see will get some infromation about the privileges the current user has on the fetched articles. (Create.Read.Update.Delete.Admin)

I have tested these apart from the whole query, these are very fast with 12.500 records (0.0004 seconds)

 

Now, the query taks 1.8229 seconds for execution, if I remove the ORDER BY then it takes 0.0384 seconds, pretty big difference..

If I prefix the query with EXPLAIN then you get the result wich can be seen in the attachment.

 

Below I will post the table structure, I am not really familliar with indexes but learning a lot about it last days.

 

Table structures:

 

-- 
-- Tabel structuur voor tabel `articles_items`
-- 

CREATE TABLE `articles_items` (
  `id` int(10) NOT NULL auto_increment,
  `id_comments_containers` int(10) NOT NULL default '0',
  `id_security_boxes` int(10) NOT NULL default '0',
  `id_articles_categories` int(10) NOT NULL default '0',
  `title` varchar(255) character set latin1 collate latin1_general_ci NOT NULL,
  `author_name` varchar(255) character set latin1 collate latin1_general_ci NOT NULL,
  `publish_date` date NOT NULL default '0000-00-00',
  `date_creation` datetime NOT NULL default '0000-00-00 00:00:00',
  `date_last_edit` datetime NOT NULL default '0000-00-00 00:00:00',
  `id_users_accounts` int(10) NOT NULL default '0',
  `tags` varchar(255) character set latin1 collate latin1_general_ci NOT NULL,
  `readCount` int(10) NOT NULL default '0',
  `active` tinyint(1) NOT NULL default '0',
  `declined` tinyint(1) NOT NULL default '0',
  `id_articles_types` int(10) unsigned NOT NULL default '1',
  `content` text NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `security` (`id_security_boxes`),
  KEY `comments` (`id_comments_containers`),
  KEY `category` (`id_articles_categories`),
  KEY `article_type` (`id_articles_types`),
  KEY `active` (`active`),
  KEY `declined` (`declined`),
  KEY `sorting` (`publish_date`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=504 ;

-- --------------------------------------------------------

-- 
-- Tabel structuur voor tabel `articles_types`
-- 

CREATE TABLE `articles_types` (
  `id` int(11) NOT NULL auto_increment,
  `id_security_boxes` int(10) unsigned NOT NULL default '0',
  `title` varchar(45) NOT NULL default '',
  `article_class` varchar(255) NOT NULL default '',
  `form_class` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

-- --------------------------------------------------------

-- 
-- Tabel structuur voor tabel `security_acl`
-- 

CREATE TABLE `security_acl` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `id_security_groups` int(10) unsigned default NULL,
  `id_users_accounts` int(10) unsigned default NULL,
  `id_security_boxes` int(10) unsigned NOT NULL default '0',
  `create` int(10) unsigned NOT NULL default '0',
  `read` int(10) unsigned NOT NULL default '0',
  `update` int(10) unsigned NOT NULL default '0',
  `delete` int(10) unsigned NOT NULL default '0',
  `admin` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  KEY `Groups` (`id_security_groups`),
  KEY `Accounts` (`id_users_accounts`),
  KEY `SecurityBoxes` (`id_security_boxes`),
  KEY `crud` (`read`,`delete`,`update`,`create`,`admin`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=12282 ;

-- --------------------------------------------------------

-- 
-- Tabel structuur voor tabel `users_accounts`
-- 

CREATE TABLE `users_accounts` (
  `id` int(11) NOT NULL auto_increment,
  `id_security_boxes` int(11) NOT NULL default '0',
  `id_security_control` int(11) NOT NULL default '0',
  `username` varchar(45) character set latin1 NOT NULL default '',
  `email` varchar(255) character set latin1 NOT NULL default '',
  `activated` tinyint(1) default '0',
  `deleted` tinyint(1) default '0',
  `creationCompleted` tinyint(1) unsigned NOT NULL default '0',
  `password` blob NOT NULL,
  `signup_date` datetime NOT NULL default '0000-00-00 00:00:00',
  `system_account` tinyint(1) NOT NULL default '0',
  `last_active` datetime NOT NULL default '0000-00-00 00:00:00',
  `last_location` blob NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `Security` (`id_security_boxes`,`id_security_control`),
  KEY `activated_deleted` (`activated`,`deleted`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC AUTO_INCREMENT=77 ;

 

Greetz

 

Note; I am dutch, excuse me for the poor english

 

[attachment deleted by admin]

Link to comment
Share on other sites

Hi

 

Your English is infinitely better than my Dutch.

 

Looks like the biggest issue is that the 2 subselects are being joined inefficiently (ie, using tempory and filesort).

 

About to go out, but will have a play when I get back. Suspect you might be able to avoid using the subselects.

 

Also, on the subselects you are only grouping by 1 of the 3 non aggregate columns. MySQL seems to cope with this, but most flavours of SQL will not cope with it and it is probably best avoided (ie if id_users_accounts varies for the same id_security_boxes, which one should it pick up?).

 

All the best

 

Keith

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.