V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
yakczh
V2EX  ›  Python

mysql 单表扫描大数据测试

  •  
  •   yakczh · 2013-11-18 15:16:52 +08:00 · 4320 次点击
    这是一个创建于 4023 天前的主题,其中的信息可能已经有所发展或是发生改变。
    环境
    Intel(R) Core(TM) i3-3210 CPU @ 3.20GHz
    DDR3 mem 4g
    ST500DM002-1BD142 500g
    xp sp3
    mysqld 5.6.13

    建表

    CREATE TABLE `test100w` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT,
    `subject` varchar(200) CHARACTER SET utf8 NOT NULL,
    `content` text CHARACTER SET utf8 NOT NULL,
    `ctime` int(10) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

    插入随机数据
    import MySQLdb
    from time import *
    from time import clock
    from random import *
    start=clock()

    now = time()

    try:
    conn=MySQLdb.connect(host='localhost',user='root',passwd='display',db='bench',port=3306,charset='utf8')
    cur=conn.cursor()
    i=1
    while i< 100*10000:
    rand=randint(10000, 99999)
    sql = "insert into test100w(subject, content,ctime) values ('%s', '%s',%d)" % ("testdata_"+str(rand),"somedata_"+str(rand),now )
    #query="select * from test200w where subject like '%%%s' " % str(rand)
    print sql
    try :
    count=cur.execute(sql)
    conn.commit()
    except Exception,e:
    print e
    conn.rollback()

    i=i+1

    cur.close()

    conn.close()
    except MySQLdb.Error,e:
    print "Mysql Error %d: %s" % (e.args[0], e.args[1])
    finish=clock()
    print (finish-start)/1000000


    查询
    import MySQLdb
    from time import clock
    from random import *
    start=clock()


    try:
    conn=MySQLdb.connect(host='localhost',user='root',passwd='display',db='bench',port=3306,charset='utf8')
    cur=conn.cursor()
    rand=randint(10000, 99999)
    query="select * from test100w where subject like '%%%s' " % str(rand)
    print query
    count=cur.execute(query)
    print 'there has %s rows record' % count
    result=cur.fetchone()
    print result
    #print 'ID: %s info %s' % result
    #results=cur.fetchmany(5)
    #for r in results:
    # print r
    cur.close()
    conn.close()
    except MySQLdb.Error,e:
    print "Mysql Error %d: %s" % (e.args[0], e.args[1])
    finish=clock()
    print (finish-start)/1000000

    结果
    100w 1.45214545424e-06
    200w 2.183407109e-06
    400w 4.3417384053e-06
    16 条回复    1970-01-01 08:00:00 +08:00
    vietor
        1
    vietor  
       2013-11-18 15:27:18 +08:00
    你想证明用mysql做“主题查询足够了”,不需要“分词索引”那些额外系统?
    yakczh
        2
    yakczh  
    OP
       2013-11-18 15:48:26 +08:00
    @vietor 是要做分表,看一个表分多大合适才不会影响到正常的业务应用
    sohoer
        3
    sohoer  
       2013-11-18 17:52:50 +08:00
    范围很重要
    likexian
        4
    likexian  
       2013-11-18 18:19:25 +08:00
    xp,400万,大数据,想什么呢?洗洗睡吧
    yakczh
        5
    yakczh  
    OP
       2013-11-18 19:09:13 +08:00
    @likexian 这个测试只是找一个分成单表的数据桶的大小阈值,实际的数据有14亿,类似象全国省,市,县,区这种行政区划的查询,从任一级都有查询的需求,从姓名,关键性字段,业务时间段, 保证查询能在3-5秒能有响应
    icyalala
        6
    icyalala  
       2013-11-18 19:35:48 +08:00
    @yakczh
    这么说是国企咯~ 怎么不用oracle?
    yakczh
        7
    yakczh  
    OP
       2013-11-18 20:35:42 +08:00
    @icyalala  oracle也装不了14亿吧
    victor
        8
    victor  
       2013-11-18 21:37:44 +08:00
    @yakczh 14亿?是我们的户口数据么?
    yakczh
        9
    yakczh  
    OP
       2013-11-18 23:34:31 +08:00
    @victor 恭喜你,答对了
    soli
        10
    soli  
       2013-11-19 09:07:17 +08:00
    有结果,没结论。
    yakczh
        11
    yakczh  
    OP
       2013-11-19 10:10:55 +08:00
    @soli 结果就是分表的单表容量保持在 500w以下
    yakczh
        12
    yakczh  
    OP
       2013-11-19 10:30:34 +08:00
    总数据容量 /500 =表数 , 每个表当作一个存储单元 ,维护一个映射表,查询和插入,更新都通过隐射找到对应的存储单元
    wangchen
        13
    wangchen  
       2013-11-19 14:30:41 +08:00
    @yakczh 你的查询语句中的`like` 部分,如果以% 开头,是无法使用索引的。

    另外,还是要从应用的实际需要去考虑存储、查询要使用什么技术。比如是频繁写,还是频繁读?读是全文检索,还是结构化查询?
    yakczh
        14
    yakczh  
    OP
       2013-11-19 15:00:48 +08:00
    @wangchen 就是测试无索引的全表扫秒的极限值,有索引的情况千差万别,跟索引的数据分布有关系, 不同的数据分布各不相同,只有这个全表扫描情况下才有确切的数值
    实际应用中有 根据姓名来模糊搜索的,比如姓张,张王这种的,而且比较多,查询时间限制在3s之内有结果
    bombless
        15
    bombless  
       2013-11-21 07:37:43 +08:00
    查询为主的就好办了……自古以来解决大量数据查询的不二法则就是多浪费存储空间……
    最简单的想法就是,根据搜索的类型的需要,每次有新的搜索类型的时候就根据那个类型的特点来划分数据存储的位置把数据分组存放,搜索的时候在确定有目标数据的地方搜就可以了~
    yakczh
        16
    yakczh  
    OP
       2013-11-21 09:25:46 +08:00
    @bombless 这种是索引的思路,根据索引能查找数据这种情况基本可以忽略,但不幸的是,不是所有数据都能完全索引的,即使是在根据索引找到的结果集范围中,最后还是要落实到Handler read rnd next的查找中,而这个搜索用的时间与索引查找的时间不是一个数量级,就跟光纤到户的最后一公里一样,最终影响整个链路总时间的最大因素是由最后一段接入的速度决定的,如果能找到不用索引仅靠扫描表就能找到的数据量阈值,就能决定存储数据(其中会有一部分是不能索引的)的容量要保持在多少范围内
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   962 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 20:25 · PVG 04:25 · LAX 12:25 · JFK 15:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.