【问题标题】:MySQL optimization of huge tableMySQL对大表的优化
【发布时间】:2011-07-30 07:03:02
【问题描述】:

我一直在尝试对某个 SELECT 查询进行一些速度改进。 情况如下: 有一个(在我眼里)巨大的交叉表。它目前有大约 2000 万行,但我预计这会增长很多。 基于这个交叉表,我需要创建另一个表。为此,我需要执行以下查询:

SELECT hugeCrossingTable.field3, otherTable.field1, hugeCrossingTable.field2 * otherTable.field3 AS someName
FROM hugeCrossingTable 
INNER JOIN otherTable ON hugeCrossingTable.field1 = otherTable.field2

现在这会产生大约一百万行。我已经在 2 个表中的两个 field1 上都有索引,但是仍然需要 18 分钟才能完成.. 我考虑过拆分表,但后来我需要找到一种方法来拆分数据,因为它只是一个交叉表,所以没有想到如何做到这一点。

关于如何优化它的任何想法?

谢谢。

根据要求,这里是创建语句:

CREATE TABLE  `hugeCrossingTable` (
  `field` int(11) NOT NULL,
  `field1` int(11) NOT NULL,
  `field2` double(10,5) DEFAULT NULL,
  `field3` int(4) DEFAULT NULL,
  KEY `field1` (`field1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE  `otherTable` (
  `field` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `field1` int(10) unsigned NOT NULL,
  `field2` int(10) unsigned NOT NULL,
  `field3` decimal(5,2) NOT NULL,
  PRIMARY KEY (`field`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

还有解释输出:

id, select_type, table              , type , possible_keys, key     , key_len, ref                , rows, Extra
1 , 'SIMPLE'   , 'otherTable'       , 'ALL', ''           , ''      , ''     , ''                 , 294 , ''
1 , 'SIMPLE'   , 'hugeCrossingTable', 'ref', 'field1'     , 'field1', '4'    , 'otherTable.field2', 69  , 'Using where'

【问题讨论】:

  • 向我们展示CREATE TABLE 语句和查询的EXPLAIN 输出。如果索引正确,但您有非常具体的范围,PARTITIONING 该表可能会有所帮助。
  • JOIN 是大表的恶魔。您几乎只想通过索引或主键访问该大小的表。您可以更改表格式以适应查询,甚至可以使用临时内存表吗?这可以使您在查询时间从几分钟到几毫秒。请记住,标准化并不意味着速度。
  • 您正在加载所有记录??为什么??存档数据/记录不是一个坏主意(如果您确定不再需要它!)
  • 所以你正在基于另一个表中的行子集创建一个新表,例如插入到 target_table (x,y) select x,y from source table ?
  • @Rudie :这都是实时数据。我每 30 分钟运行一次此查询。 @f00:我首先通过其他一些查询获取返回集,看看它们是否与当时需要的匹配,然后将结果放在另一个表中。 @Twisted Pear:关于如何做到这一点的任何建议? @Wrikken:就像我说的,我想把桌子分开,但因为它是一个交叉表,我不知道怎么做!

标签: mysql optimization


【解决方案1】:

这里有一些 innodb 示例,它们适用于大约 . 60 到 5 亿行,展示了精心设计的 innodb 表的优势以及如何最好地使用聚集索引(仅适用于 innodb)

MySQL and NoSQL: Help me to choose the right one

60 million entries, select entries from a certain month. How to optimize database?

Rewriting mysql select to reduce time and writing tmp to disk

您还需要阅读以下内容:

http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html

http://www.xaprb.com/blog/2006/07/04/how-to-exploit-mysql-index-optimizations/

整理好表设计并优化 innodb 配置后:

http://www.mysqlperformanceblog.com/2006/09/29/what-to-tune-in-mysql-server-after-installation/

http://www.mysqlperformanceblog.com/2007/11/03/choosing-innodb_buffer_pool_size/

你可以试试这样的:

start transaction;

insert into target_table (x,y) select x,y from source_table order by x,y;

commit;

希望这会有所帮助。

【讨论】:

  • 哇,这看起来很有希望!已经非常感谢了。更新 20 00 万表的索引需要一些时间,一旦完成,我会回到这个。
  • 可能更快地按主键顺序选择到 outfile 然后使用加载数据 infile 导入回来 - 10 分钟 vs... 小时:P
  • 好吧,所以我从 hugeCrossingTable 中删除了 KEY field1 (field1) 并添加了 PRIMARY KEY (field1,field3) 和 otherTable 我添加了 KEY theKey (field1 ,field2),这使查询时间缩短到 4 秒。 (也许这样做会更快,但我一夜之间就完成了,所以没问题!)
  • 哦,应该是 4 毫秒。对不起!
  • 这个优化对于阅读来说很棒,但是写作呢?我有一个大约 1/4 大小(但当然会增长)的表,它写入了很多,但也经常读取(写入 > 读取)。读取大约需要 30 秒,而且写入速度也不是很快。关于如何减少两个查询的时间的任何想法?添加更多索引只会使阅读速度更快
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
  • 1970-01-01
相关资源
最近更新 更多