如何通过字符串连接加速INSERT SELECT

时间:2012-07-26 17:03:43

标签: mysql sql performance insert-select

我想调用insert select,我尝试使用此select(在此INSERT SELECT query when one column is unique的帮助下)

SELECT minids.userid, username, password, full_name, country, email,
      (select openclipart_files.id from aiki_users, openclipart_files
       where aiki_users.userid = users.userid and avatar like '%svg' AND
             filename = avatar) as avatar,
      homepage, usergroup, notify, nsfwfilter
FROM aiki_users users
INNER JOIN (SELECT MIN(userid) as userid FROM aiki_users GROUP by username) 
           minids ON minids.userid = users.userid;

我将它与插入

一起使用
INSERT INTO openclipart_users(id, user_name, password, full_name, country,
email, avatar, homepage, user_group, notify, nsfw_filter) SELECT ...

执行需要很长时间(几分钟后取消)

aiki_users表有100k行,openclipart_files有30k行,基本上我只是将所有东西从aiki_users复制到openclipart_users跳过重复项,我希望avatar是文件的id,旧表是一个字符串(只有大约300个用户有svg)大约1k用户的头像有非'化身,但我只是svg)。

有没有办法快速插入那个头像(没有它INSERT SELECT执行几秒钟)到openclipart_users,任何可行的解决方案都可以(很快我的意思是不到一分钟)。

编辑关于SELECT的解释输出

+----+--------------------+-------------------+--------+---------------+----------+---------+----------------------------------+--------+-------------+
| id | select_type        | table             | type   | possible_keys | key      | key_len | ref                              | rows   | Extra       |
+----+--------------------+-------------------+--------+---------------+----------+---------+----------------------------------+--------+-------------+
|  1 | PRIMARY            | <derived3>        | ALL    | NULL          | NULL     | NULL    | NULL                             | 106689 |             |
|  1 | PRIMARY            | users             | eq_ref | PRIMARY       | PRIMARY  | 4       | minids.userid                    |      1 |             |
|  3 | DERIVED            | aiki_users        | index  | NULL          | username | 302     | NULL                             | 111273 | Using index |
|  2 | DEPENDENT SUBQUERY | openclipart_files | ALL    | NULL          | NULL     | NULL    | NULL                             |  37715 |             |
|  2 | DEPENDENT SUBQUERY | aiki_users        | eq_ref | PRIMARY       | PRIMARY  | 4       | openclipart_staging.users.userid |      1 | Using where |
+----+--------------------+-------------------+--------+---------------+----------+---------+----------------------------------+--------+-------------+

4 个答案:

答案 0 :(得分:2)

转换为仅加入语法(删除相关子查询并加入子选择):

SELECT minids.userid, username, password, full_name, country, email,
      clip.id as avatar,
      homepage, usergroup, notify, nsfwfilter
FROM aiki_users users
INNER JOIN (SELECT MIN(userid) as userid FROM aiki_users GROUP by username) 
           minids ON minids.userid = users.userid
LEFT OUTER JOIN openclipart_files clip ON 
           clip.owner = users.userid AND RIGHT(users.avatar, 3) = 'svg' 
           AND clip.filename = users.avatar

尝试一下。

答案 1 :(得分:0)

一些改进:

SELECT MINIDS.USERID, USERNAME, PASSWORD, FULL_NAME, COUNTRY, EMAIL,
       (SELECT OPENCLIPART_FILES.ID
          FROM OPENCLIPART_FILES
         WHERE AVATAR LIKE '%svg' AND USERS.FILENAME = AVATAR) AS AVATAR, 
       HOMEPAGE, USERGROUP, NOTIFY, NSFWFILTER
  FROM     AIKI_USERS USERS
       INNER JOIN
           (SELECT MIN(USERID) AS USERID
              FROM AIKI_USERS
            GROUP BY USERNAME) MINIDS
       ON MINIDS.USERID = USERS.USERID;

答案 2 :(得分:0)

SELECT 
    MIN(userid), username, password, full_name, country, email,
    openclipart_files.id,
    homepage, usergroup, notify, nsfwfilter
FROM aiki_users 
LEFT JOIN openclipart_files  ON filename = avatar AND avatar like '%svg'
GROUP BY username

答案 3 :(得分:0)

使用@SPFiredrake提示CASE和RIGHT我创建此查询

SELECT minids.userid, username, password, full_name, country, email,
       case RIGHT(avatar, 3) 
       when 'svg' then 
            (select openclipart_files.id 
             from openclipart_files
             where filename = users.avatar AND users.userid = owner)
       else 
            null 
       end as avatar, homepage, usergroup, first_login, notify, nsfwfilter
FROM aiki_users users 
INNER JOIN (SELECT MIN(userid) as userid FROM aiki_users GROUP by username) 
minids ON minids.userid = users.userid;

在2-4秒内运行(内部SQL仅针对这300个案例运行)。