【问题标题】:CREATE TABLE AS SELECT killing MySQLCREATE TABLE AS SELECT 杀死 MySQL
【发布时间】:2010-11-27 17:44:17
【问题描述】:

我们在相当强大的硬件(具有 8 个 Xeon 内核、8Gb RAM 和 RAID10 的 HP DL360)上运行具有中等负载 (200-300 QPS) 的 MySQL 服务器。所有表都是 innodb 并且活动数据集适合分配的innodb_buffer_pool_size

我们的数据库是规范化的,为了减少连接的数量,我们使用物化视图来展平数据集。由于数据每天分批添加几次,MV:s 使用CREATE TABLE AS SELECT 重新生成,而不是使用复杂的触发器动态更新。

问题在于,有时在运行这些 CREATE 查询时(每个查询需要 5 到 50 秒),其他与服务器无关的查询似乎在 CREATE 查询后面排队,导致无响应数据库。

为了(重新)生成 MV:s 我们使用这样的东西:

BEGIN TRANSACTION;
DROP TABLE IF EXISTS TableName_TMP;
CREATE TABLE TableName_TMP ENGINE=INNODB CHARACTER SET utf8 COLLATE utf8_swedish_ci AS 
    SELECT about100columns, and10Expressions 
    FROM Table1 
    JOIN Table2 ON Table1.fk = Table2.pk 
    /* join up to 13 other tables */
    WHERE ((removed IS NULL OR removed = 0)) 
    ORDER BY created DESC, id ASC;
ALTER TABLE TableName_TMP ADD PRIMARY KEY(id), INDEX(created);
DROP TABLE IF EXISTS TableName;
ALTER TABLE TableName_TMP RENAME TO TableName;
COMMIT;

SELECT 的 EXPLAIN 产生如下内容:

+----+-------------+------------------+-------------+---------------+------------+---------+------------------------------+-------+-----------------------------+
| id | select_type | table            | type        | possible_keys | key        | key_len | ref                          | rows  | Extra                       |
+----+-------------+------------------+-------------+---------------+------------+---------+    ------------------------------+-------+-----------------------------+
|  1 | SIMPLE      | Table1           | ref_or_null | removed       | removed    | 5       | const                        | 76093 | Using where; Using filesort | 
|  1 | SIMPLE      | Table2           | eq_ref      | PRIMARY       | PRIMARY    | 4       | Table1.fk1                   |     1 |                             | 
|  1 | SIMPLE      | Table3           | eq_ref      | PRIMARY       | PRIMARY    | 4       | Table1.fk2                   |     1 |                             | 
/* More of the same */
|  1 | SIMPLE      | TableN           | eq_ref      | PRIMARY       | PRIMARY    | 4        | TableM.fk                    |     1 | Using index                 | 
|  1 | SIMPLE      | TableX           | eq_ref      | PRIMARY       | PRIMARY    | 4       | TableY.fk                    |     1 |                             | 
/* More of the same */    
+----+-------------+------------------+-------------+---------------+------------+---------+------------------------------+-------+-----------------------------+

知道为什么CREATE TABLE AS 会使我们的服务器完全超载,我该如何防止它?

问候,

【问题讨论】:

  • 在 SQL Server 中,执行 SELECT ... INTO(与 CREATE TABLE ... SELECT 相同的概念)会锁定整个源表,从而导致其他查询排队。这是设计使然。 MySQL 上可能有类似的行为。由于我也不了解 MySQL,所以我没有把这个放在正确的答案中。
  • 好像是这样 - mysqlperformanceblog.com/2006/07/12/… 。我打算星期一做一些测试。
  • 如果您想让您的评论被接受为正确答案,请重新发布作为答案。

标签: sql mysql transactions materialized-views


【解决方案1】:

我们通过切换到 SELECT INTO 和 LOAD DATA INFILE 解决了这个问题,就像 http://www.mysqlperformanceblog.com/2006/07/12/insert-into-select-performance-with-innodb-tables/ 一样。非常感谢 Randolph Potter 让我们朝着正确的方向前进。

【讨论】:

    【解决方案2】:

    这可能是原因吗?

    注意:DROP TABLE 会自动提交当前活动事务,除非您使用 TEMPORARY 关键字。

    (http://dev.mysql.com/doc/refman/5.1/en/drop-table.html)

    【讨论】:

    • 谢谢,我会将事务更改为仅包含 CREATE TABLE 和 ALTER TABLE 语句。但是,我看不出这将如何成为我的问题的根源,因为仅 CREATE TABLE 语句就会使服务器过载,并且仅一个语句不应该从事务性能方面受益,对吧?
    猜你喜欢
    • 2013-06-29
    • 1970-01-01
    • 2020-11-27
    • 1970-01-01
    • 2020-02-08
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    相关资源
    最近更新 更多