数据库缓慢检索/更新/插入问题,每个表中有超过 500 万条记录

Posted

技术标签:

【中文标题】数据库缓慢检索/更新/插入问题,每个表中有超过 500 万条记录【英文标题】:Database slow retriving/updating/inserting problem with more than 5mil records in each table 【发布时间】:2009-12-25 15:30:45 【问题描述】:

如何构建数据库以避免减速? (引擎:MyISAM)

目前我在一个表中有超过 500 万条记录的数据库,这会导致数据检索缓慢。 我目前正在寻找构建数据库的方法以避免这种数据库。 (数据库引擎 MyISAM)

导致问题的表是帖子和 cmets,每个表都有超过 500 万条记录。

我有一个想法,在按日期保存记录时使用文本文件作为存储,这样每个文件都包含足够的数据,不会减慢检索和保存过程,但是对于数据库我不知道该怎么做:(

有什么方法可以在 mysql 数据库中保存数据(每条记录大约 500 万条记录),以免导致数据检索、插入或更新缓慢?

“帖子”结构

    CREATE TABLE IF NOT EXISTS `ibf_posts` (
  `pid` int(10) NOT NULL auto_increment,
  `append_edit` tinyint(1) default '0',
  `edit_time` int(10) default NULL,
  `author_id` mediumint(8) NOT NULL default '0',
  `author_name` varchar(32) default NULL,
  `use_sig` tinyint(1) NOT NULL default '0',
  `use_emo` tinyint(1) NOT NULL default '0',
  `ip_address` varchar(16) default NULL,
  `post_date` int(10) default NULL,
  `icon_id` smallint(3) default NULL,
  `post` text,
  `queued` tinyint(1) NOT NULL default '0',
  `topic_id` int(10) NOT NULL default '0',
  `post_title` varchar(255) default NULL,
  `new_topic` tinyint(1) default '0',
  `edit_name` varchar(255) default NULL,
  `post_key` varchar(32) default NULL,
  `post_parent` int(10) NOT NULL default '0',
  `post_htmlstate` smallint(1) NOT NULL default '0',
  `post_edit_reason` varchar(255) default NULL,
  PRIMARY KEY  (`pid`),
  KEY `topic_id` (`topic_id`,`queued`,`pid`,`post_date`),
  KEY `author_id` (`author_id`,`topic_id`),
  KEY `post_date` (`post_date`),
  KEY `ip_address` (`ip_address`),
  KEY `post_key` (`post_key`),
  FULLTEXT KEY `post` (`post`),
  FULLTEXT KEY `post_2` (`post`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

查询:

SELECT p.*, pp.*,.id,m.name,m.mgroup,m.email,m.joined,m.posts, m.last_visit, m.last_activity,m.login_anonymous,m.title,m.hide_email, m.warn_level, m.warn_lastwarn, m.points, m.topics_started, m.skin,
                    me.msnname,me.aim_name,me.icq_number,me.signature, me.website,me.yahoo,me.location, me.avatar_location, me.avatar_type, me.avatar_size, m.members_display_name, m.custom_post_css, m.custom_right_img
                    m.custom_post_color
                        FROM posts p
                            LEFT JOIN members m ON (m.id=p.author_id)
                            LEFT JOIN profile_portal pp ON (m.id=pp.pp_member_id)
                            LEFT JOIN member_extra me ON (me.id=m.id)
                        WHERE p.pid IN(--post ids here) 
                        ORDER BY --ordering here

【问题讨论】:

你能提供你正在使用的数据库结构和查询吗? 你能显示 ORDER BY 子句中的内容吗? 【参考方案1】:

5M 没那么多。

可能你的表索引错误。

请发布您的查询,我们可能会告诉您如何改进它。

更新:

SELECT  p.*, pp.*,.id,m.name,m.mgroup,m.email,m.joined,m.posts, m.last_visit, m.last_activity,m.login_anonymous,m.title,m.hide_email, m.warn_level, m.warn_lastwarn, m.points, m.topics_started, m.skin,
        me.msnname,me.aim_name,me.icq_number,me.signature, me.website,me.yahoo,me.location, me.avatar_location, me.avatar_type, me.avatar_size, m.members_display_name, m.custom_post_css, m.custom_right_img
        m.custom_post_color
FROM    posts p
LEFT JOIN
        members m
ON      m.id = p.author_id 
LEFT JOIN
        profile_portal pp
ON      pp.pp_member_id = m.id
LEFT JOIN
        member_extra me
ON      me.id = m.id
WHERE   p.pid IN (--post ids here) 
ORDER BY
        --ordering here

确保:

members.idPRIMARY KEY member_extra.idPRIMARY KEY 您在profile_portal.pp_member_id 上有一个索引

你也省略了ORDER BY 子句,但这个子句也很重要,使用索引也可以改进它。

【讨论】:

我在第一篇文章中添加了结构【参考方案2】:

EXPLAIN PLAN 会告诉你查询引擎是如何做的。如果你看到“表扫描”,你就知道你需要索引。

【讨论】:

【参考方案3】:

一张表中的 500 万行并不多,您的查询需要多长时间?我怀疑您可能对索引有一些问题。 EXPLAIN 语句可能有助于找出您的查询实际在做什么。

如果您有正确索引的表和健全的查询,您可以查看partitioning.。

编辑:

如果在表 ibf_posts 上添加 INDEX(pid, author_id) 或 INDEX(author_id, pid) 有帮助,您可以尝试。

【讨论】:

以上是关于数据库缓慢检索/更新/插入问题,每个表中有超过 500 万条记录的主要内容,如果未能解决你的问题,请参考以下文章

mysql-插入更新删除数据

无法使用 pyodbc 在 Access 数据库的表中插入/更新长文本字段

jdbc实现批量给多个表中更新数据(解析Excel表数据插入到数据库中)

当超过 10k 数据时,Laravel 数据表加载缓慢

如何从表中检索票数最高的候选人姓名[关闭]

一个表中有超过 3000 万个条目,执行一次选择计数需要 19 分钟