• 第一次操刀数据库分表的教训与经验


    给数据库分表,曾经是个离我很遥远的事情,入行这几年参与过别人主导的分表、分库工作,自己从未操刀,直到我自己的垃圾小站主表10多万记录,相关的其他表30~40万,孱弱的服务器面对谷歌和百度的抓取,导致下载一个页面的时间非常长(PS:谷歌的蜘蛛是我小站的主要用户)。

    image

    因为我抓取的主要是stackoverflow、微软社区、雅虎问答等和计算机相关的数据库,存储比较简单,分这么几个表

    1:url表,记录每个问题原始的url地址 10万

    2:问题内容表,记录问题的主要内容 10万

    3:答案表;记录问题的答案 20万

    4:用户信息表 20万

    5:问题和tag的关系表 30万

    我存储的时候比较简单,用问题的title 的哈希值作为唯一值,防止问题重复

    以前看过一些文章,关于数据库分表分库的主要是数据的均匀和可扩展性方面的考虑,我考虑常见的几种方式

    1:按照时间分表----因为我的采集程序是我想开就开,想关就关,没有时间规律,所以不能这么干

    2:按照分类分表----我主要有两个分类1是网站分类,二是tag分类,网站的分类的话stackoverflow的数据占了70%,tag分类的话也不是很均匀,因为我是按照关键词抓取信息的

    3:一个障碍,我现在的网站url里面没有分类和时间信息,如果按照分类和时间分表,根据url信息取不到数据了

    4:一个侥幸,好在我没把自增id作为url一部分,仅仅是作为优化数据库的标配(记不清在那里看过,有主键的表比没主键的表好,有自增id比没自增id的好)

    最后我决定根据我的title的哈希值分表,因为url地址里面包含了这个东西,根据哈希值就可以找到这个表

    磨刀霍霍分表,一个表是拆10个表?100个表?1000表?,我是根据哈希值的后三位分表 例如后三位是123 表就是table_123,最后为了防止出现数据不均匀,我一个表拆分1000张,虽然然该集中的还在集中,但是分完表后,一个表要达到10万数据应该是猴年马月的事情了

    我的数据库是mysql的,园子里的一个牛人的分表工具很好使

    http://www.cnblogs.com/hb_cattle/archive/2011/10/12/2208910.html  这是地址,最重要的是,这是我在园子里面下载的代码里面唯一有单元测试的代码,用过之后,发现有单元测试的东西质量果然有保证,坚定了我学习单元测试的决心

    于是我三下五除二分了8000张表出来,这个时候遇到了郁闷的问题

    如何快速有效的吧数据从原来的表里取出来,在放到我新的表里面去,我写了存储过程效果奇差,分一个表要20~40分钟,这在正式生产环境是绝对不允许的,我的代码如下,

    DELIMITER $$
    
    USE `learn`$$
    
    DROP PROCEDURE IF EXISTS `genQu`$$
    
    CREATE DEFINER=`root`@`localhost` PROCEDURE `genQu`()
    BEGIN
      DECLARE i INT DEFAULT 0;
      DECLARE l_sql VARCHAR(4000);
      WHILE i <1000  DO
      SET l_sql=CONCAT("INSERT  INTO question_",i," SELECT * FROM question WHERE  RIGHT(question.titlecode,3)=",i);
      SET @SQL=l_sql;
      SELECT  @SQL;
      PREPARE s1 FROM @SQL;
      EXECUTE s1;
      DEALLOCATE PREPARE s1;
      SET i = i + 1;
      END WHILE;
    END$$
    
    DELIMITER ;

    因为我去数据的查询语句走不了索引,所以导致我去数据异常缓慢,这算是这次分表的一个教训

    教训1:分表时候要考虑取数据和插入数据的性能问题

    虽然慢,但是还可以接受,每天晚上弄一个表,1周就把所有的表弄完了

    分完表后,我开始改程序,抓取程序和web站点读写数据的部分,我查了一下,

    我抓取数据用的orm http://viciproject.com/wiki/projects/mvc/home 彻底不支持分表和分库

    我做web站点用的orm https://github.com/toptensoftware/PetaPoco 支持的不是很友好

    于是我用园子里面的orm,结果悲剧的一幕开始了,面对一个库8000张表,园子里面4大orm的模型生成工具都不能很好的工作,

    教训2:分表前,先要选好orm工具和生成实体类

    虽然PetaPoco 不是很友好的支持分表,但是,他简单代码少,很容易就找到了支持分表的方法。

    经验3:工具选的越简单越单一,遇到麻烦好处理

    于是我开始修改代码,一周后,网站和抓取程序上线,我原以为谷歌抓等待的时间会下降,服务器的cpu和内存和下降,结果悲剧的一幕出现了。

    1 监控显示内存急速上升,1G内存就剩下100M了,郁闷的我计划学习lucene,结果还没开工内存就没了咬牙切齿

    image

    2谷歌抓取显示等待时间

    image

    到底是什么问题导致了mysql和iis内存上升了( mysql200M、iis300M),悲剧的是我以前没留意mysql和iis分别用多少内存,一时半会不知道2个东西那个出了问题

    教训4:服务器性能监控数据很重要,发现问题可以快速定位

    到底是那里除了问题?本着我写的程序无bug的态度,必然是mysql的问题,因为分表的sql语句太简单了,mysql处理8张表和8000张表的配置应该不一样吧。。。。。。。

    经过乱起八糟的查找,mysql有一个配置

    SHOW GLOBAL STATUS LIKE 'open%tables%'

    好像是配置打开文件的数量等相关的配置还有一些,可见mysql里面放8000张表和8张表在配置上的确有些区别,因为不是很懂mysql,所以就不研究了,

    教训5:分表前要对数据库做基本的随机读写压力测试,测试适合的配置。。。。。。。。。。

    应该是我的程序写的有问题

    程序有问题改咋整呢,和上次的程序除了分表的sql貌似没啥区别,第一次装vs2012,看看vs2012的内存采样能不能猜出问题

    可能因为我是手工点击的,没能模仿谷歌爬虫,vs2012的内存采样没有猜出问题

    教训6:性能检测不能过分依赖工具

    程序到底是那里有问题呢?

    这次比上个版本读取数据库唯一的区别是我直接调用了一个orm不鼓励调用的方法,主要是不这么干,就没法支持分表了

    learnDAL.learnDB.GetInstance()
            public static IFactory Factory { get; set; }
            public static learnDB GetInstance()
            {
                if (_instance != null)
                    return _instance;
    
                if (Factory != null)
                    return Factory.GetInstance();
                else
                {
                    //备注以前是 return  new learnDB()
                    _instance = new learnDB();
                    return _instance;
                }
            }

    于是我调试了一下,跟进去,虽然没有明显的错误,但是感觉每次new一个对象貌似不靠谱,于是我小改一下,本地测试正常读取数据没问题,让谷歌蜘蛛去做并发测试吧吐舌鬼脸

    上线后,内存就下来了!至于速度有没有提升,需要等几天谷歌抓取统计信息才可以看出来

    image

    内存又有了,lucene可以走起了!

  • 相关阅读:
    一个把数据转化成Excel导出的程序 python Django
    Ubuntu常用命令
    Git 常用命令 和 安装
    strick-footer 粘边布局
    Django
    CSS基础 和 font字体、背景属性连写 与 清除浮动方法
    MySQL 40题练习题和答案
    JS(ES6)、Vue.js、node.js
    ORM框架 和 面向对象编程
    MySQL基本指令3 和 索引 、分页
  • 原文地址:https://www.cnblogs.com/qqloving/p/3414999.html
Copyright © 2020-2023  润新知