2012-07-26 27 views
1

我想插入呼叫选择,我尝试使用这个选择(从这个INSERT SELECT query when one column is unique帮助)如何加快INSERT SELECT与加入了串

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表有10万行和openclipart_files有30K行,基本上我刚从aiki_users到OP复制所有的东西enclipart_users跳过重复项,我希望头像是旧表中文件的id,在旧表中是一个字符串(只有约300个用户有1k用户的svg头像不具有''头像,但我只有svg)。

是否有任何方法可以快速插入该头像(没有它在几秒钟内执行INSERT SELECT)到openclipart_users中,任何可以工作的solustion都会很好(我很快意味着少于一分钟)。

编辑解释过的输出选择

 
+----+--------------------+-------------------+--------+---------------+----------+---------+----------------------------------+--------+-------------+ 
| 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 | 
+----+--------------------+-------------------+--------+---------------+----------+---------+----------------------------------+--------+-------------+ 
+0

需要多长时间才能运行SELECT? EXPLAIN对此有何评论? – Vatev 2012-07-26 17:15:09

+0

需要多少时间才能获取所选的所有行? – hmmftg 2012-07-26 17:16:37

+1

与几乎所有的SQL DB一样,当你的源表很大或者你的子查询表很大时,子查询是非常糟糕的。通过使用LIKE运算符来复合这一点,与直接比较相比,这是一个非常昂贵的条件运算符(尝试'RIGHT(avatar,3)='svg''并查看它如何比较)。看看你是否可以将它重构为只使用连接(包括加入子查询)。例如,尝试加入'SELECT avatar,CASE RIGHT(avatar,3)'svg'THEN 1 ELSE 0 END AS IsSVG FROM openclipart_files' with avatar = filename and IsSVG = 1. – SPFiredrake 2012-07-26 17:21:18

回答

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 

尝试了这一点。

+0

但是只有300行通过filename = avatar加入,当'avatar不喜欢'%svg'' – jcubic 2012-07-28 07:11:52

+0

这就是为什么它是左连接(左外连接)时,我需要所有100k的NULL值。连接语法确保它仅创建匹配记录IF AND ONLY如果连接谓词匹配。否则,所有没有匹配的行的“剪辑”列都将为空。 – SPFiredrake 2012-07-30 13:26:49

+0

我不知道,我知道只有SQL的子集,需要了解更多关于JOIN的信息。我需要测试你的解决方案,如果它能工作,我会接受你的答案,然后我的黑客更好。 – jcubic 2012-07-30 13:41:43

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; 
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 
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个案例运行)。