MySQL Query作为SELECT快速运行,挂起INSERT ... SELECT或CREATE TABLE ... SELECT

时间:2017-03-31 02:18:54

标签: mysql

这里有一个真正的头颅。以下是我的两个测试表来说明:

CREATE TABLE IF NOT EXISTS `atest` (
  `id` int(10) unsigned NOT NULL DEFAULT '0',
  `testval` double DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `testval` (`testval`)
) ENGINE=MyISAM DEFAULT CHARSET=UTF8;

CREATE TABLE IF NOT EXISTS `atestb` (
  `id` bigint(16) NOT NULL DEFAULT '0',
  `lookup` bigint(16) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `lookup` (`lookup`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

表中有太多记录要粘贴数据值,但您可以在此处下载包含数据的表: https://dl.dropboxusercontent.com/u/2301830/lookuptest.sql

我的问题:我必须在atestb.lookup中找到第一个记录,该记录大于或等于atest.testval中atest中每条记录的值。

尝试了几种不同的方法之后,得出这个结果的最快方法是:

SELECT a.id, a.testval, 
 (SELECT lookup 
     FROM atestb
     WHERE lookup >= a.testval
     ORDER BY lookup LIMIT 1)
  AS closest
 FROM atest a

这样既有效又快速。但问题是我需要使用此查询来创建新表。在这种情况下,它是一个临时表,但我已经尝试使用永久表并获得相同的结果。如果我跑:

CREATE TEMPORARY TABLE tmptbl
   SELECT a.id, a.testval, 
    (SELECT lookup 
     FROM atestb
     WHERE lookup >= a.testval
     ORDER BY lookup LIMIT 1)
     AS closest
FROM atest a

它只是无限期挂起“发送数据......”而且我必须终止这个过程。我也尝试创建表,然后使用INSERT INTO TABLE tmptbl,我得到相同的结果。

问题显然在于子查询派生列,因为如果我将其留下或替换不同的值,它就可以工作。如果atest中只有少量记录,它也有效,但实际表有45K记录。

如果有另一种方法在没有子查询的情况下进行查询,那也没关系,但是这样的话:

 SELECT a . * , MIN( b.lookup )
    FROM `atest` a
    LEFT JOIN atestb b ON b.lookup >= a.testval
    GROUP BY a.id
由于联接在> =上,

...也非常低效。所以它也挂了。我的子查询效果很好......但它不会插入到表中。

EXPLAIN的结果(无论是普通的SELECT还是INSERT ... SELECT都是一样的):

id | select_type        |table   |type   | possible_keys | key    | key_len | ref  | rows | Extra
       -------------------------------------------------------------------------------------------------------------------------------------
 1 | PRIMARY            | a      | ALL   | NULL          | NULL   | NULL    | NULL |45886 | NULL
 2 | DEPENDENT SUBQUERY | atestb | index | lookup        | lookup | 8       | NULL |    1 | Range checked for each record (index map: 0x2); Using index`

知道这里发生了什么吗?

0 个答案:

没有答案