如何在大表中改善插入时间?

时间:2012-04-18 12:00:38

标签: mysql database

我们在MySQL表中有以下数据结构,它基本上记录了页面上的用户操作

id int
page_id int
user_id int
action_type enum(6)
date_created datetime`

我们有以下索引:

id Primary key
user_id-page_id-date_created unique
page_id-user_id-date_created
user_id
page_id-date_created

我们的问题是,该表目前有1.25亿行,并且以每天80万的速度增长,这使得插入需要大约2个小时才能完成。 插入是通过3个查询进行的,这些查询从3个其他表中选择数据。我们可以做些什么来改善这个时间? 我们应该删除mysql并尝试其他数据库解决方案吗?

L.E:根据您的反馈,我想提供更多信息。 首先,这些表是MyISAM,这些插入在cron作业中每晚发生一次,我们不会从中删除任何数据。 这是我如何处理插入。我将大表称为big_table,并且3个表中的每一个都是content_table,因为它们在结构上相似。解释将是3张表中最大的一张,大约有1.085亿张。首先我得到我应该开始使用php插入的id。 (我很好用非索引查询的3分钟来获得它)

SELECT id FROM content_table WHERE date_created > "2012-04-18" ORDER BY id ASC LIMIT 1;
+-----------+
| id        |
+-----------+
| 107278872 |
+-----------+
1 row in set (3 min 15.52 sec)

EXPLAIN SELECT id FROM content_table WHERE date_created > "2012-04-18" ORDER BY id ASC LIMIT 1;
+----+-------------+------------------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table            | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+------------------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | content_table    | index | NULL          | PRIMARY | 4       | NULL |    1 | Using where |
+----+-------------+------------------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.06 sec)

然后使用此ID我执行以下操作

INSERT IGNORE INTO big_table (user_id, page_id, type, date_created) 
SELECT user_id, page_id, IF (is_admin,"admin_action","action") as type, created_time FROM content_table WHERE id >= "107278872";

以下是选择的解释如何

EXPLAIN SELECT user_id, page_id, IF (is_admin,"admin_action","action") as type, created_time FROM content_table WHERE id >= "107278872";
+----+-------------+------------------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table            | type  | possible_keys | key     | key_len | ref  | rows   | Extra       |
+----+-------------+------------------+-------+---------------+---------+---------+------+--------+-------------+
|  1 | SIMPLE      | content_table    | range | PRIMARY       | PRIMARY | 4       | NULL | 777864 | Using where |
+----+-------------+------------------+-------+---------------+---------+---------+------+--------+-------------+
1 row in set (0.00 sec)

我也在phpmyadmin中尝试了它并获得了大约0.004s的时间,所以我认为这是插入需要时间而不是数据获取。我所知道的服务器是它是一个四核xeon @ 2.4 ghz和16 GB的ram,但我对存储一无所知(只要我有这个信息就会回来)。并且数据不仅用于日志记录,我们需要具有哪些用户在页面上最活跃的统计数据,各种分组等,并且用户可以为这些设置指定任何间隔。

3 个答案:

答案 0 :(得分:3)

你可以:

  1. EXPLAIN计划您在其他3个表上运行的查询,以查看它们是否已正确编入索引。表SCAN应该被删除。
  2. 为查询中的每个WHERE子句添加索引到这三个其他表。
  3. 按日,周,月或其他一些合适的机制对数据进行分区,以便将最旧的数据移出到报告/仓储解决方案。
  4. 您可以看到触发器解决方案是否可以帮助您。
  5. 对数据库进行配置并监控网络流量,以查看花费的时间。
  6. 所有关系数据库都将不得不处理太多数据。你的第一个想法不应该是放弃MySQL;它应该弄清楚你的归档策略需要什么。您必须确定在给定时间内事务存储中需要多少数据。

答案 1 :(得分:0)

影响插入的因素很多,例如

  • 引擎类型
  • 索引
  • 如何插入数据等。

首先告诉我们你是如何插入数据的,第二件事是存储引擎用于表,然后我们可以进一步优化你插入查询,一般来说我可以说不必要的索引意味着插入速度慢。

有关插入速度read this article of dev.mysql for insert speed.

的更多说明

答案 2 :(得分:0)

你是如何插入它们的?您每秒只能有一定数量的事务循环查询,如此

//start loop
insert into table values (1) 
//end loop

慢很多
//start loop
//fill a variable 
//end loop
insert into table values (1),(2),(3),(4) // where (1),(2),(3),(4) are values filled by the loop

(请注意,您不能插入太多像这样的值,尝试使用您的数据,我通常会发现200左右的值非常好)

你没有大量的索引,所以我不认为它们会引发问题,phpmyadmin显示索引大小,检查与总表大小相比的内容 - 这可能会让你知道它是否存储过多< / p>