mysql - 如何优化mysql索引,让读写频繁的大表快速INSERT操作?

标签 mysql optimization indexing

我有一个表格监视列表,其中包含今天将近 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。使用索引需要 <0.2 秒。

问题在于, INDEXES 产品页面本身的加载时间越来越长,因为随着表的增长,写入操作需要超过 5 秒。此外,每次查看产品页面时,mysqld 进程的可用 CPU 达到 10-15%(大约每 2 秒一次)。我们已经不得不升级服务器硬件,因为在以前的服务器上它达到 100% 并导致 mysqld 崩溃。

我的计划是尝试 2 表解决方案。一个表用于 INSERT 操作,另一个表用于 SELECT 操作。我计划在 INSERT 表达到 1000 条记录时使用 TRIGGER 清除,并将最早的 900 条记录复制到 SELECT 表中。报告页面是实时(最近查看)和分析(哪个区域)的混合体,但实时页面往往只需要少量的新记录,而分析页面不需要知道最近的趋势(即最近 1000 次浏览)。所以我可以用小表做前者,用大表做后者报告。


我的问题:这是该问题的理想解决方案吗?

此外:在 MySQL 中使用 TRIGGERS 是否可以优化 trigger_statement,使其花费更长的时间,但不会消耗太多 CPU?每 30 分钟运行一次 cron 作业 是否更好,并且在需要时执行清除是更好的解决方案吗?

最佳答案

将单行写入数据表的操作应该不会花费 5 秒,无论表有多大。

你的聚簇索引是基于timestamp字段的吗?如果不是,它应该是,所以你不会在 table 中间的某个地方写字。此外,请确保您使用的是 InnoDB 表 - MyISAM 未针对写入进行优化。

我建议写入两个表:一个长期表,一个短期报告表,很少或没有索引,然后根据需要转储。

另一种解决方案是为实时报告数据使用内存缓存或内存数据库,这样就不会对生产数据库造成影响。

再想一想:这些报告中的任何一个到底应该有多“活”?也许定时检索新列表而不是每次 页面浏览一次就足够了。

关于mysql - 如何优化mysql索引,让读写频繁的大表快速INSERT操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1102378/

相关文章:

mysql - 将值从数据库插入到VBA中的本地表

c++ - GNU 编译器优化

r - 使用 R,如何使用主成分创建和索引?

python - 将字符串切成 3 组并重叠

php - 如何使用 .ajax 提取 mysql 数据并用它填充表单

Mysql查询连接三个表

mysql - JOIN 查询的 ORDER BY

Clang 与 1 优化的倒数

c++ - 如果函数未在类声明中定义,则性能损失

sql - 优化 SQL 表的性能 - 索引