加快mysql表的创建(来自select)

时间:2017-05-25 23:18:56

标签: mysql performance temp-tables

我的查询运行时间约为1.6秒,返回150Kish行。我一直在从这个查询构建一个基于内存引擎的临时表,这个操作大约需要6.5秒。我已经通过mysql网站上的大量文档进行筛选,并且在临时表上使用了索引(当我有索引时没有任何差别而没有它们)试图找到表创建的某种方式表现更好一点。有没有人对配置选项有什么建议可以加快创建内存临时表(或非临时表)?要清楚我正在寻找的是什么(我认为)是某种表配置选项可能会提高创建的速度。我已经浏览了mysql 5.7网站上列出的大部分内容,但似乎没有任何改变在内存中创建临时/标准表所需的时间。

CREATE TEMPORARY TABLE 
IF NOT EXISTS myTempTable 
(ugID INT,stID INT, INDEX st (`st`) ) 
ENGINE=MEMORY AS 
select ugID, stID 
from a_complex_query_that_runs_in_under_2_seconds_but_takes_6_to_write_to_a_temptable_with_150k_rows


id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY <derived15> ALL NULL    NULL    NULL    NULL    559 
1   PRIMARY creatorEntity   eq_ref  PRIMARY PRIMARY 4   creatorAssignment.OwnerObjectID 1   Using index
1   PRIMARY <derived2>  ALL NULL    NULL    NULL    NULL    152580  Using where; Using join buffer
15  DERIVED VMAssignment    ref AssociatedObjectID,AssociatedObject AssociatedObject    2       2902    Using where
2   DERIVED test_   range   AssignmentValue,AssociatedObjectID,AssociatedObject,assignmentQuery AssociatedObjectID  4   NULL    214 Using where; Using temporary; Using filesort
2   DERIVED cfv_    ref CustomFieldID,EntityID,CFEntity,CFValue,CFEntityValue   CustomFieldID   4   testCloud.test_.AssignmentValue 4232    Using where
2   DERIVED ent_    ref VMStoreID   VMStoreID   4   testCloud.cfv_.EntityID 1   Using index
3   UNION   test_   ref AssociatedObjectID,AssociatedObject AssociatedObject    2       2902    Using where; Using temporary; Using filesort
3   UNION   cfv_    ref CustomFieldID,EntityID,CFEntity,CFValue,CFEntityValue   CFValue 772 func,func   4   Using where
3   UNION   ent_    ref VMStoreID   VMStoreID   4   testCloud.cfv_.EntityID 1   Using index
4   UNION   test_   const   PRIMARY PRIMARY 4       1   Using index
5   UNION   test_   index_merge AssociatedObjectID,AssociatedObject AssociatedObjectID,AssociatedObject 4,6 NULL    1   Using intersect(AssociatedObjectID,AssociatedObject); Using where; Using index; Using temporary; Using filesort
5   UNION   entity_ ref PRIMARY,ClassName   ClassName   2       23326   Using where
5   UNION   ent_    ref VMStoreID   VMStoreID   4   testCloud.entity_.ID    1   Using index
6   UNION   entity_ ref PRIMARY,ClassName   ClassName   2       23326   Using where; Using temporary; Using filesort
6   UNION   ent_    ref VMStoreID   VMStoreID   4   testCloud.entity_.ID    1   Using index
6   UNION   test_   ref AssignmentValue,AssociatedObjectID,AssociatedObject,assignmentQuery AssignmentValue 768 testCloud.entity_.State 1   Using where
7   UNION   entity_ ref PRIMARY,ClassName   ClassName   2       23326   Using where; Using temporary; Using filesort
7   UNION   ent_    ref VMStoreID   VMStoreID   4   testCloud.entity_.ID    1   Using index
7   UNION   test_   ref AssignmentValue,AssociatedObjectID,AssociatedObject,assignmentQuery AssignmentValue 768 testCloud.entity_.Zip   1   Using where
8   UNION   test_   range   AssociatedObjectID,AssociatedObject AssociatedObjectID  4   NULL    150 Using where; Using temporary; Using filesort
8   UNION   entity_ ref PRIMARY,ClassName,Address   Address 456 func,func   4   Using where
8   UNION   ent_    ref VMStoreID   VMStoreID   4   testCloud.entity_.ID    1   Using index
9   UNION   test_   range   AssignmentValue,AssociatedObjectID,AssociatedObject,assignmentQuery AssociatedObjectID  4   NULL    203 Using where; Using temporary; Using filesort
9   UNION   ent_    ref VMStoreID   VMStoreID   4   testCloud.test_.AssignmentValue 1   Using where; Using index
10  UNION   test_   const   PRIMARY PRIMARY 4       1   Using index
11  UNION   test_   ref AssociatedObjectID,AssociatedObject AssociatedObjectID  4       1   Using where; Using temporary; Using filesort
11  UNION   entity_ ref PRIMARY,ClassName   ClassName   2       23326   Using where
11  UNION   ent_    ref VMStoreID   VMStoreID   4   testCloud.entity_.ID    1   Using index
12  UNION   test_   ref AssignmentValue,AssociatedObjectID,AssociatedObject,assignmentQuery AssociatedObject    2       2902    Using where; Using temporary; Using filesort
12  UNION   ent_    ref VMStoreID   VMStoreID   4   testCloud.test_.AssignmentValue 1   Using where; Using index
13  UNION   test_   range   AssignmentValue,AssociatedObjectID,AssociatedObject,assignmentQuery AssociatedObjectID  4   NULL    239 Using where; Using temporary; Using filesort
13  UNION   list_stores ref VMListID,VMStoreID,VMStoreID_2,VMStoreID_3,VMStoreID_4,VMStoreID_5,VMStoreID_6,VMStoreID_7,VMStoreID_8,VMStoreID_9,VMStoreID_10,VMStoreID_11,VMStoreID_12,VMStoreID_13,VMStoreID_14,VMStoreID_15,VMStoreID_16   VMListID    4   testCloud.test_.AssignmentValue 318 Using where
13  UNION   ent_    ref VMStoreID   VMStoreID   4   testCloud.list_stores.VMStoreID 1   Using index
14  UNION   test_   range   AssignmentValue,AssociatedObjectID,AssociatedObject,assignmentQuery AssociatedObjectID  4   NULL    70  Using where; Using temporary; Using filesort
14  UNION   sto_    ref PRIMARY,RetailerID  RetailerID  4   testCloud.test_.AssignmentValue 63  Using where; Using index
14  UNION   ent_    ref VMStoreID   VMStoreID   4   testCloud.sto_.ID   1   Using index
NULL    UNION RESULT    <union2,3,4,5,6,7,8,9,10,11,12,13,14>   ALL NULL    NULL    NULL    NULL    NULL    

3 个答案:

答案 0 :(得分:2)

没有太多可以合作的地方。 (SHOW CREATE TABLEEXPLAIN)但我确实看到了一件事:

Using intersect(AssociatedObjectID,AssociatedObject)

使用“复合材料”几乎总能改善这种情况。指数:

INDEX(AssociatedObjectID, AssociatedObject)

复合索引可能还有其他情况,但我们需要查看查询。

&#34;但是查询填充临时表所需的时间&#34; - 创建152K行可能比插入那么多行花费更长的时间。

尝试使用ENGINE=InnoDB代替ENGINE=MEMORY。 InnoDB取得了很大的进步。

另请注意不要在INDEX st (st)中添加CREATE,而是在之后添加CREATE。逐步构建索引可能MEMORY中最慢的部分。

可能没有可调参数会影响 req = Request("http://www.someUrlWithXml.com", headers={'Connection': 'keep-alive', 'Cache-Control': 'max-age=0', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, sdch', 'Accept-Language': 'cs,en-GB;q=0.8,en;q=0.6'}) xml = urlopen(req).read() 的性能。

答案 1 :(得分:0)

首先要做的是找出瓶颈所在。正如其他人在评论中所建议的那样,它不是填写临时表。

插入150k行

大约需要5秒钟。哇,这让我看起来很愚蠢,但我会在以后赎回自己。

   $dbh->query('CREATE TEMPORARY TABLE IF NOT EXISTS myTempTable (ugID INT,stID INT, INDEX st (`st`) r ');
   $dbh->beginTransaction();

   $stmt = $dbh->prepare("INSERT INTO myTempTable(ugId,stID) values(:u, :s)");

   for ($i=0; $i < 150000 ; $i++) {
       $stmt->execute(array("u"=> $i, "s"=> $i));
   }
   $res = $dbh->query("SELECT COUNT(*) from myTempTable");

   $dbh->commit();

像表一样创建表

上面的实验很糟糕,因为它循环150k次,实际上也许。但是如果我们像上面那样创建一个永久表然后做了CREATE TABLE LIKE(毕竟这是原始问题)呢

BTW从上面的代码中删除TEMPORARY关键字将时间增加到大约9秒。现在在mysql控制台中。

mysql> CREATE TEMPORARY TABLE  IF NOT EXISTS myTempTable  (ugID INT,stID INT, INDEX st (`stId`) )  ENGINE=MEMORY AS (SELECT * FROM ugTable);
Query OK, 150000 rows affected (0.17 sec)
Records: 150000  Duplicates: 0  Warnings: 0

一秒的分数。很明显,错误的是加载数据的方式而不是填充表格的过程。

减少IO。

您的复杂查询会读取很多行。一组大表中的150k行是很多IO。通过确保服务器有足够的内存来缓存内存中涉及的整个表集,可以大大提高速度。

如果磁盘上的数据大小较小,那将会容易得多。也许是时候重新检查你的表格,看看你是否错过了标准化步骤。是时候看看是否可以更改某些索引。例如,您有一些重要的索引,如AssignmentValue 768。即使使用这些索引,这仍然是相当多的IO。

在将150k的数据加载到内存中的临时表之前,必须先在磁盘上读取所有这些数据。

答案 2 :(得分:0)

建议在使用数据填充表格后创建索引。这将减少您的运行时间。这背后的理论是索引将在插入之后作为整体在内存中创建,然后将被写入磁盘,这比使用每个插入更新索引快得多。在插入后创建索引时,索引也将具有完美的树形布局。