【发布时间】:2010-11-09 07:08:56
【问题描述】:
我有一个表关注列表,其中包含今天近 300 万条记录。
mysql> select count(*) from watchlist;
+----------+
| count(*) |
+----------+
| 2957994 |
+----------+
它被用作记录大型电子商务网站(超过 50,000 种产品)上产品页面浏览量的日志。它记录了查看产品的productID、查看者的IP地址和USER_AGENT。以及发生时间的时间戳:
mysql> show columns from watchlist;
+-----------+--------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+-------------------+-------+
| productID | int(11) | NO | MUL | 0 | |
| ip | varchar(16) | YES | | NULL | |
| added_on | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
| agent | varchar(220) | YES | MUL | NULL | |
+-----------+--------------+------+-----+-------------------+-------+
然后在整个网站的后端(例如检查 GoogleBot 索引的内容)和前端(例如“最近查看的产品”的侧边栏框和显示用户“您所在地区的人也喜欢”等)。
为了让这些“报告”页面和侧边栏快速加载,我将索引放在相关字段上:
mysql> show indexes from watchlist;
+-----------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-----------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| watchlist | 1 | added_on | 1 | added_on | A | NULL | NULL | NULL | | BTREE | |
| watchlist | 1 | productID | 1 | productID | A | NULL | NULL | NULL | | BTREE | |
| watchlist | 1 | agent | 1 | agent | A | NULL | NULL | NULL | YES | BTREE | |
+-----------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
如果没有索引,例如带有侧边栏的页面将花费大约 30-45 秒执行查询以获取 7 个最近的 ProductID。使用索引需要
问题在于, 使用 INDEXES,产品页面本身的加载时间越来越长,因为随着表的增长,写入操作需要 5 秒以上的时间。此外,每次查看产品页面(大约每 2 秒一次)时,mysqld 进程都会出现峰值,相当于可用 CPU 的 10-15%。我们已经不得不升级服务器硬件,因为在以前的服务器上它达到了 100% 并导致 mysqld 崩溃。
我的计划是尝试 2-table 解决方案。一个表用于 INSERT 操作,另一个表用于 SELECT 操作。我计划在 INSERT 表达到 1000 条记录时使用 TRIGGER 清除,并将最旧的 900 条记录复制到 SELECT 表中。报告页面是实时(最近查看)和分析(哪个区域)的混合体,但实时页面往往只需要少量新记录,而分析页面不需要知道最近的记录趋势(即最后 1000 次观看)。所以我可以将小表用于前者,而将大表用于后者的报告。
我的问题:这是解决这个问题的理想方案吗?
另外:在 MySQL 中使用 TRIGGERS 是否可以很好地 触发 trigger_statement,使其花费更长的时间,但不会消耗太多 CPU?每 30 分钟运行一次 cron 作业 会不会是更好的解决方案?
【问题讨论】:
-
只是为了说明您一次要插入多少条记录?您是否按照 Adam 的建议批量加载?
-
您是否考虑过使用 INNOdb,以便获得行级锁定,而不是像 MyISAM 那样锁定整个表。
-
每次插入一条记录。我可以试试 InnoDB
标签: mysql optimization indexing