0

我们在 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并尝试其他数据库解决方案吗?

LE:根据您的反馈,我正在尝试提供更多信息。首先,这些表是 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.004 秒的时间,所以我认为是插入需要时间,而不是数据获取。我对服务器的了解是它是一个四核 xeon @ 2.4 ghz 和 16 GB 的内存,但我对存储一无所知(我一有这些信息就会回来)。并且数据不用于记录,我们只需要统计哪些用户在页面上最活跃,各种分组等,用户可以为这些指定任何时间间隔。

4

3 回答 3

3

你可以:

  1. 解释您在其他 3 个表上运行的查询的计划,以查看它们是否被正确索引。应该消除 TABLE SCAN。
  2. 为查询中的每个 WHERE 子句向这三个其他表添加索引。
  3. 按天、周、月或其他合适的机制对数据进行分区,以便您可以将最旧的数据移到报告/仓储解决方案中。
  4. 您可以查看触发解决方案是否可以帮助您。
  5. 分析数据库并监控网络流量以查看时间花费在哪里。

所有关系数据库都将不得不处理过多的数据。你的第一个想法不应该是放弃 MySQL;它应该弄清楚您的归档策略需要是什么。您必须确定在给定时间您的事务存储中需要多少数据。

于 2012-04-18T12:05:46.150 回答
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 显示索引大小,检查与总表大小相比的内容 - 这可能会让您了解它是否存储过多

于 2013-06-27T21:39:21.813 回答
0

影响刀片的因素很多,例如

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

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

有关插入速度的更多说明,请阅读 dev.mysql 的这篇文章以了解插入速度。

于 2012-04-18T12:15:13.883 回答