简体   繁体   中英

Lots of temporary tables in MySQL

I am running website which i have below two queries which are very much repetitive. And in MySQL innoDB processes in can see they are taking lots of time and whenever i see processes those are there they keep on creating temporary tables and takes long to execute taking lots of memory and CPU.

They were really bad i somehow manage to optimised these.. but i am not able to do beyond that.

$getmoddetails =    "SELECT a.id, a.name, a.defvar, a.description, a.icon, a.thumb, a.average_rating, a.total_rating, c.rating, a.group_access, d.long_name, a.editor_id, e.users_count
        FROM dir_cat_item AS b
        INNER JOIN dir_item AS a ON a.id = b.item_id
        AND a.status = 'O'
        LEFT JOIN dir_item_notation_user_map AS c ON a.id = c.item_id
        AND c.user_id =%u 
        LEFT JOIN users AS d ON d.id = a.editor_id
        LEFT JOIN (SELECT item_id, COUNT(*) AS users_count
            FROM   module
            GROUP BY item_id) AS e ON e.item_id = b.item_id
        WHERE a.id=%u";


$getnbModules_by_col = "SELECT 
                            posx,COUNT(posx) as nb 
                        FROM module WHERE 
                            user_id = %u 
                            AND profile_id = %u 
                        GROUP BY posx
                        ORDER BY posx ASC";

Table index on Module

- item_id
- user_id
- profile_id
- uniq

For USERS Table

- id
- username

Any suggestion please...

Update :-

CREATE TABLE IF NOT EXISTS `module` (
  `item_id` mediumint(8) unsigned NOT NULL DEFAULT '0',
  `user_id` int(10) unsigned NOT NULL DEFAULT '0',
  `profile_id` int(3) unsigned NOT NULL DEFAULT '0',
  `posx` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `posy` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `posj` tinyint(3) unsigned NOT NULL DEFAULT '0',
  `x` smallint(5) unsigned NOT NULL DEFAULT '0',
  `y` smallint(5) unsigned NOT NULL DEFAULT '0',
  `typ` char(1) CHARACTER SET utf8 NOT NULL DEFAULT 'D',
  `variables` text COLLATE utf8_unicode_ci,
  `uniq` smallint(5) unsigned NOT NULL DEFAULT '1',
  `blocked` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `minimized` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `old_id` tinyint(3) unsigned DEFAULT NULL,
  `feed_id` mediumint(8) unsigned NOT NULL DEFAULT '0',
  `shared` varchar(33) COLLATE utf8_unicode_ci DEFAULT NULL,
  `currentview` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  KEY `item_id` (`item_id`,`user_id`,`profile_id`,`uniq`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

item_id 18  A   No  
user_id 393467  A   No
profile_id  393467  A   No
uniq    393467  A   No

Thank you in advance

For best performance of that second query, you'd need an appropriate index on the module table, eg

...  ON module (user_id, profile_id, posx)

For the first query, you'd likely benefit from a different index on the module table:

... ON module (item_id)

But without the table definitions, datatype and cardinality of the columns, it's really impossible to make definitive suggestions.

In your first query, I'd suggest you add a predicate in the inline view (derived table) aliased as e . I don't think MySQL is pushing the predicate from the outer query into the inline view.

    ( SELECT item_id
           , COUNT(*) AS users_count
        FROM module
       WHERE item_id = %u
       GROUP BY item_id
    ) AS e

You're going to need to supply the same value in that WHERE clause as you are providing in the WHERE clause on the outer query. From what I'm reading there...

e.item_id = b.item_id = a.id = %u

By adding that WHERE clause in that inline view, that should cut down the number or rows retrieved from the module table, and that derived table will have just one row. An index with a leading column of item_id would be a covering index. The EXPLAIN PLAN should show Using index and not show Using filesort .


If your first query is pulling back a relatively small number of rows, you might consider a correlated subquery on the module table, in place of a join to the derived table (aliased as e ) in your first query (to avoid materializing a large derived table). (In general, however, correlated subqueries can be real performance killers. But in some cases, where the outer query is pulling back a small number of rows, the repeated execution of the subquery can actually perform better than generating a large derived table, which you only need a few rows from.)

SELECT a.id
     , a.name
     , a.defvar
     , a.description
     , a.icon
     , a.thumb
     , a.average_rating
     , a.total_rating
     , c.rating
     , a.group_access
     , d.long_name
     , a.editor_id
     , ( SELECT SUM(1)
           FROM module e
          WHERE e.item_id = b.item_id
            AND e.item_id = %u
       ) AS users_count
  FROM dir_cat_item b
  JOIN dir_item a 
    ON a.id = b.item_id
   AND b.item_id = %u 
   AND a.status = 'O'
  LEFT
  JOIN dir_item_notation_user_map c 
    ON c.item_id = a.id
   AND c.item_id = %u
   AND c.user_id = %u
  LEFT
  JOIN users d
    ON d.id = a.editor_id
 WHERE a.id = %u

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM