简体   繁体   English

MySQL中有很多临时表

[英]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. 在MySQL中,innoDB进程可以看到它们花费大量时间,并且每当我看到那里的进程时,它们就会继续创建临时表,并且要花很长时间执行并占用大量内存和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 为了使第二个查询获得最佳性能,您需要在module表上有适当的索引,例如

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

For the first query, you'd likely benefit from a different index on the module table: 对于第一个查询,您可能会受益于module表上的其他索引:

... 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 . 在您的第一个查询中,建议您在内联视图(派生表)中添加别名为e的谓词。 I don't think MySQL is pushing the predicate from the outer query into the inline view. 我认为MySQL不会将谓词从外部查询推入内联视图。

    ( 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. 您将需要在WHERE子句中提供与在外部查询的WHERE子句中提供的值相同的值。 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. 通过在该内联视图中添加该WHERE子句,应该可以减少从模块表中检索到的行数,并且该派生表将只有一行。 An index with a leading column of item_id would be a covering index. 前导item_id索引将是覆盖索引。 The EXPLAIN PLAN should show Using index and not show Using filesort . EXPLAIN PLAN应该显示正在Using index而不要显示正在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). 如果您的第一个查询要回退相对较少的行,则可以考虑在模块表上使用相关子查询,而不是在第一个查询中连接到派生表(别名为e )(以避免实现大派生)表)。 (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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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