MySQL优化嵌套的SELECT和INSERT语句

时间:2015-01-04 17:22:49

标签: mysql

我正试图找到任何方法来优化这个陈述:

INSERT INTO achievements 
(
    nick, cost, achievement_type, announced_in_chat, shown_on_stream, dt
)

SELECT nick, 2000, 0, TRUE, FALSE, NOW() 
FROM points_log

WHERE nick NOT IN 
(
    SELECT nick from achievements
    WHERE achievement_type = 0 AND stream_online = TRUE
)
GROUP BY nick HAVING SUM(amount) >= 2000;

目标是找到从points_log获得2000分(SUM(金额))并且也不在成就中的人(不是IN)。任何帮助将不胜感激。

以下是成就和points_log表:

mysql> describe achievements;
+-------------------+-----------------------+------+-----+---------+----------------+
| Field             | Type                  | Null | Key | Default | Extra          |
+-------------------+-----------------------+------+-----+---------+----------------+
| id                | mediumint(8) unsigned | NO   | PRI | NULL    | auto_increment |
| nick              | char(25)              | NO   | PRI | NULL    |                |
| cost              | decimal(8,4)          | NO   | MUL | NULL    |                |
| achievement_type  | tinyint(3) unsigned   | NO   | MUL | NULL    |                |
| announced_in_chat | tinyint(1)            | NO   |     | NULL    |                |
| shown_on_stream   | tinyint(1)            | NO   |     | NULL    |                |
| dt                | datetime              | NO   | PRI | NULL    |                |
+-------------------+-----------------------+------+-----+---------+----------------+
7 rows in set (0.01 sec)


mysql> describe points_log;
+-------------------+-----------------------+------+-----+---------+----------------+
| Field             | Type                  | Null | Key | Default | Extra          |
+-------------------+-----------------------+------+-----+---------+----------------+
| id                | mediumint(8) unsigned | NO   | PRI | NULL    | auto_increment |
| nick              | char(25)              | NO   | PRI | NULL    |                |
| amount            | decimal(10,4)         | YES  | MUL | NULL    |                |
| stream_online     | tinyint(1)            | NO   | MUL | NULL    |                |
| modification_type | tinyint(3) unsigned   | NO   | MUL | NULL    |                |
| dt                | datetime              | NO   | PRI | NULL    |                |
+-------------------+-----------------------+------+-----+---------+----------------+
6 rows in set (0.01 sec)

1 个答案:

答案 0 :(得分:1)

优化insert实际上只是优化查询:

SELECT nick, 2000, 0, TRUE, FALSE, NOW() 
FROM points_log
WHERE nick NOT IN (SELECT nick 
                   from achievements
                   WHERE achievement_type = 0 AND stream_online = TRUE
                  )
GROUP BY nick
HAVING SUM(amount) >= 2000;

我可能会将这个问题“彻底改变”:

SELECT pl.nick, 2000, 0, TRUE, FALSE, NOW() 
FROM points_log pl LEFT JOIN
     achievements a
     ON a.nick = pl.nick AND a.achievement_type = 0 AND a.stream_online = TRUE
WHERE a.nick IS NULL
GROUP BY nick
HAVING SUM(amount) >= 2000;

对于此查询,您需要achievements(nick, achievement_type, stream_online上的索引。

声明在问题中,您只是想避免nickachievements的成就。 的最简单方法是使用查询:

INSERT INTO achievements(nick, cost, achievement_type, announced_in_chat, shown_on_stream, dt)
    SELECT pl.nick, 2000, 0, TRUE, FALSE, NOW() 
    FROM points_log pl 
    GROUP BY nick
    HAVING SUM(amount) >= 2000
    ON DUPLICATE KEY SET nick = VALUES(nick);

一个独特的索引:

CREATE UNIQUE INDEX idx_achievements_nick ON achievements(nick);

但是,您的查询还有其他问题无法解决的问题。