基于PHP客户端的TokyoTyrant(TCH, TCB, TCT), Memcache, Mysql性能测试

author: selfimpr

date: 2010-07-12

email: [email protected]

blog: http://blog.csdn.net/lgg201

注: 这里会公布所有的测试脚本, 测试脚本有不足指出还请指教学习, 如果有朋友有跑出来新的数据, 烦请发一份给我, 谢谢.

测试脚本共享地址: http://blog.csdn.net/lgg201/archive/2010/07/17/5742763.aspx

测试的要点主要有 :

1. Memcache, TCH, TCB, TCT, Mysql 写入数据的性能对比 .

2. Memcache, TCH, TCB, TCT, Mysql( 根据主键 ) 读取数据的性能对比 .

3. Mysql, TCT 检索数据的性能对比 .

4. 由于网上有人说 TCH 在数据量超过内存后性能会急剧下降 , TCB 性能稳定 , 因此 , 就这个问题也将单独测试 .

测试脚本

all-get-compare.php : 所有 5 种存储产品的根据 key 获取数据的测试 , 此测试输入参数 num, 表示进行 num 次测试 , 输出为对比折线图以及各种存储产品的平均每条耗时 .

all-set-compare.php : 所有 5 种存储产品的数据写入测试 , 此测试输入参数有 num length, num 代表测试的写入次数 , length 代表每次写入的数据大小 (TCT Mysql 的写入略大于此值 ), 输出为 5 种对比折线图及各种存储产品的平均每条耗时 . 另外 , 此脚本可以接受 case 参数 ( 值为 test_tch, test_tcb, test_tct, test_memcache, test_mysql 之一 ), num length 意义同上 , case 参数是为了单独测试某种存储产品的写入耗时 , 另一方面 , 可以用此脚本插入更为合理的测试数据 ( 比存储产品自身的测试数据写入工具慢 ).

autoinsert.php : all-set-compare.php case 参数情况下的原型 .

basic_funcs.php : 基础函数 , 主要包含图表生成函数 , 随机数据生成函数 .

mysql_util.php : 一个简单的 Mysql 封装类 .

search-compare.php : 对搜索的测试 , 两个输入参数 case num, 意义同上 , 其中 case 可选值为 : test_name, test_sex, test_location, 分别是根据名称 , 性别 , 省市搜索 , 此测试只比较 TCT mysql 的性能 . 输出为两者搜索性能的对比图和平均每条耗时 .

tct_setIndex.php : TCT 中的指定列设置索引 .

tt-compare-get.php : 此测试用于 TCT, TCB, TCH 在数据量超出内存后的读取测试 , 两个输入参数 case num, case 可选值为 : test_tch, test_tcb, test_tct. 输出为带内存占用的时间线分析图 .

tt-compare-insert.php : 此测试用于 TCT, TCB, TCH 在数据量超出内存后的写入测试 , 输入参数与 tt-compare-get.php 相同 . 输出也和 tt-compare-get.php 相同 .

concurrent_mysql.php : 此测试用于 Mysql 的并发测试和一次 Mysql 操作各部分用时比例测试 .

测试结果

1: 内存比较图顶端标题有平均每条操作时间

2: 多种存储产品比较图各自的标题后有平均每条操作时间

3: 本测试中使用的时间单位一律为 e-6 , 1/1000000

TCH, TCB, TCT, Memcache, Mysql 性能对比 (key-value 存取 )

写入测试

测试脚本 : all-set-compare.php

原始数据 : Memcache , 其余都 2 亿

bnum: 4 亿

输入参数 : num=100000&length=10240

图中红色是 Mysql, 蓝色是 TCB, 黑色是 TCH, 黄色是 TCT, 绿色是 Memcache, 5 种产品平均每条数据写入时间为 :

Mysql

TCB

TCT

TCH

Memcache

181e-6

324e-6

300e-6

68e-6

39e-6

从上面的写入性能来看 , Memcache 最快 , 其次 TCH, 这两个基本在同一数量级 , 而其余三者性能相差比较大 .

读取测试 ( 根据 key)

测试脚本 : all-get-compare.php

原始数据 : Memcache , 其余都 2 亿

bnum: 4 亿

输入参数 : num=100000&length=10240

图中红色是 Mysql, 蓝色是 TCB, 黑色是 TCH, 黄色是 TCT, 绿色是 Memcache, 5 种产品平均每条数据写入时间为 :

Mysql

TCB

TCT

TCH

Memcache

90e-6

114e-6

42e-6

34e-6

25e-6

从上面的读取性能看 , 也是 Memcache 最快 , 其次是 TCH TCT, 另外两种则有较大差距 .

key-value 性能测试结论

根据上面写入和读取的性能测试来看 , Memcache, TCH 在游戏数据的存储方面备选 , 由于在查阅资料的过程中 , 发现有观点认为 TCH 在数据量超出内存后会导致性能下降 , TCB 则性能稳定 , 不受此影响 , 通过下面内存峰值是 TCB TCH 的读取写入性能测试来比较二者 .

TCH, TCB 的内存峰值插入测试

TCH 写入

测试脚本 : tt-compare-insert.php

原始数据 : 0

bnum: 400

输入参数 : case=test_tch&num=500000&length=10240

从上图对照可以得到结论 : TCH 数据库在数据量超出内存后写入性能会有明显的波动 ( 0.6 ).

TCH 读取

测试脚本 : tt-compare-get.php

原始数据 : 0

bnum: 400

输入参数 : case=test_tch&num=500000( 内存满负荷 )

输入参数 : case=test_tch&num=500000( 内存空闲 )

对比上面两图顶端标题中的平均耗时 : 内存满负荷 261.4e-6 , 内存空闲 30.05e-6 , 性能差 8 倍左右 , 因此 , 可以得到结论 : TCH 在内存满负荷后性能会下降 8 倍左右 .

TCH 在内存满负荷情况下 , 产生如下性能损耗 : 写入降低为原来的 60% 左右 , 读取性能降低为原来的 12% 左右 .

TCB 写入

测试脚本 : tt-compare-insert.php

原始数据 : 0

bnum: 400

输入参数 : case=test_tcb&num=500000&length=10240

从上图可以看出 TCB 的性能比较稳定 , 写入性能与内存消耗几乎无关 .

TCB 读取

测试脚本 : tt-compare-insert.php

原始数据 : 0

bnum: 400

输入参数 : case=test_tcb&num=500000( 内存满负荷 )

输入参数 : case=test_tcb&num=500000( 内存空闲 )


对比上面两图顶端标题中的平均耗时 : 内存满负荷 197.22e-6 , 内存空闲 32.25e-6 , 性能差 8 倍左右 , 因此 , 可以得到结论 : TCB 在内存满负荷后性能会下降 8 倍左右 .

TCB 在内存满负荷情况下 , 产生如下性能损耗 : 写入降低为原来的 60% 左右 , 读取性能降低为原来的 12% 左右 .

TCB, TCH 的内存峰值性能测试数据

TCH 读取

TCH 写入

TCB 读取

TCB 写入

内存满

261e-6

207e-6

197e-6

539e-6

内存空

31e-6

32e-6

由此表格可以看出 , TCB 在内存满时读取上的平均优势为 60e-6 秒左右 , TCB 的写入性能约为 TCH 50%, 由上面图表分析可以证实网上查阅得到的 TCH 在数据量超过内存容量后性能下降 , 但是 , TCB 的读取也会有所下降 , 究其整体运行的性能来看 , TCH 优于 TCB.

因此 , 对于游戏部分的存储 , 在目前的三种备选方案 TCH, TCB, Memcache , 又将 TCB 淘汰出局 .

在仅剩的 TCH Memcache , 但从速度而言 , Memcache 有无可比拟的优势 , 但是 , 从另一个角度来看 , Memcache 作为一个纯粹的缓存产品 , 不能够独立的处理数据存储业务 , 因此 , 如果使用 Memcache 作为 key-value 的存储接口 , 那么为了数据的持久化及其安全性 , 必然要使用某种持久化存储工具去实现 .

如果 Memcache 再套一个持久化存储工具 , 那么这中间必然会带来一定的性能损失 , 从另一方面来讲 , Memcache 外加持久化工具 , 必然要增加编程实现上的难度 , 也就是间接的增大项目风险 .

从安全性方面来讲 , TT 系列的数据库都提供了备份和还原接口 , 能够支持完整备份和增量备份 , 也能够支持指定时间的恢复 , Memcache 在这一方面也要比 TT .

TCT Mysql 的检索测试


测试数据量在第一部分讨论过 , 以单表 1.6 亿为准 , 但是 , 由于 Mysql 用来写入测试数据的程序在 7000 万数据以后变得很慢 , 所以 , Mysql 只插入了 7000 万数据 , TCT 使用上面建立的数据库 , 2 亿条初始数据 .

根据名字检索

测试脚本 : search-compare.php

原始数据 : Mysql7000 , 其余都 2 亿

bnum: 4 亿

输入参数 : case=test_name&num=20( 由于 Mysql 这里不使用索引 , 性能极低 , 所以使用 20 条检索测试 )

图中蓝色为 Mysql, 黑色为 TCT, 可以看出 , 此时 TCT 的性能远高于 Mysql 并且平稳 , 此时使用的查询条件为 like ‘%%’, Mysql 不使用索引 . TCT 的包含查询仍然能够使用文本索引

图中平均每条搜索时间为 TCT: 22568e-6 , Mysql:5103998e-6

根据性别检索

测试脚本 : search-compare.php

原始数据 : Mysql7000 , 其余都 2 亿

bnum: 4 亿

输入参数 : case=test_name&num=20000

图中蓝色为 Mysql, 黑色为 TCT, 此时 , 根据性别检索的条件为 =’’, Mysql 使用索引 , 并且由于是 = 条件 , 所以 Mysql 可以使用常量表优化 , TCT 使用文本索引 , 可以看到 , Mysql 性能优于 TCT.

图中平均检索时间为 TCT: 1456e-6, Mysql: 25e-6.

根据省市查询

测试脚本 : search-compare.php

原始数据 : Mysql7000 , 其余都 2 亿

bnum: 4 亿

输入参数 : case=test_location&num=20000

图中 Mysql 是蓝色线 , TCT 是黑色线 , Mysql 性能高于 TCT. 此时 Mysql 是根据情况在 province city 两列上选择索引匹配 , 并且由于 = 存在 , Mysql 可以使用常量表优化 . TCT 使用 province 作为主索引 , city 作为辅助索引检索

图中每条检索平均耗时为 TCT: 189e-6 , Mysql:28e-6

所有条件一起检索

测试脚本 : search-compare.php

原始数据 : Mysql7000 , 其余都 2 亿

bnum: 4 亿

输入参数 : case=test_all&num=20000

图中 Mysql 是蓝色线 , TCT 是黑色线 , Mysql 性能高于 TCT. 此时 Mysql 是根据情况在 province city 两列上选择索引匹配 , 并且由于 = 存在 , Mysql 可以使用常量表优化 . 与省市检索一样 , 这里没有用到 sex 索引 .

图中每条检索平均耗时为 TCT: 190e-6 , Mysql:27e-6

关系数据库对比结果

TCT

Mysql

索引生效

190e-6

27e-6

索引无效

22568e-6

5103998e-6

Mysql 在索引无法使用时 , 表现比 TCT , 但只要能使索引生效 , Mysql 的性能就会高于 TCT, 分析游戏中需要检索排序的数据 :

找人 : 需要对玩家的 name uid 进行 %% 方式的检索 , 在单独使用这两条检索时 , 无法命中索引 , 但是 , 这种检索的数据量为每玩家一条 , 也就是单表 50-100 万条左右 , 根据经验在这个范围内 Mysql 的全表扫描性能也能满足需求 .

日记 , 系统消息等检索 : 这些表数据量会比较大 , 但是这些表中建立索引都是可以命中的 .

寄售商品 : 与日记 , 系统消息相似 , 索引有效 , 并且数据量更小 .

排名 : 数据量与找人相同 , 但索引有效 .

TCT 在这一方面存在的另一个缺陷是只能支持单表 , 这实际上就导致了单表数据量增大 , 即便对于原本小数据量的表 , 在这种情况下 , 也会变成大数据量 .

补充 1: mysql 连接过程耗时测试

10 万次操作 , 每次操作包括以下操作 : 连接 ( 打开连接 , 选择数据库 , 设置数据库编码 ), 一条更新 10 行的 update, 一条取前 10 条的全表扫描检索 , 一条 insert 单条的 insert, 关闭连接 .

按照上述分块 , 操作过程中的平均时间为


补充 2: Mysql 并发连接测试

使用上述测试 Mysql 操作分块的代码 , 利用 apache ab 进行并发连接测试 . 开启 10000 并发做 10000 次请求 , 得到以下结果 :

一万并发 , 一万请求

Server Software: nginx/0.7.62

Server Hostname: localhost

Server Port: 80

Document Path: /end/concurrent_mysql.php?num=1

Document Length: 193 bytes 文档大小

Concurrency Level: 10000 并发连接数

Time taken for tests: 3.384 seconds 所有请求耗时

Complete requests: 10000 完成请求数

Failed requests: 733 失败请求数

(Connect: 0, Receive: 0, Length: 733, Exceptions: 0)

Write errors: 0

Non-2xx responses: 9350 HTTP 响应头非 2xx 的数量

Total transferred: 3525248 bytes 总传输量

HTML transferred: 1900140 bytes HTML 传输量

Requests per second: 2955.47 [#/sec] (mean) 每秒平均请求数

Time per request: 3383.552 [ms] (mean) 平均事务时间 ( 毫秒 )

Time per request: 0.338 [ms] (mean, across all concurrent requests) 平均每条并发请求独立的响应时间 ( 毫秒 )

Transfer rate: 1017.46 [Kbytes/sec] received 传输速度 ( 接收 )

Connection Times (ms)

min mean[+/-sd] median max

Connect: 0 218 706.9 10 3064

Processing: 3 41 100.5 11 973

Waiting: 1 36 100.0 8 971

Total: 6 259 729.2 21 3287

Percentage of the requests served within a certain time (ms)

50% 21 50% 的请求在 21 毫秒内响应

66% 22

75% 26

80% 47 80% 的请求在 47 毫秒内响应

90% 559

95% 3071

98% 3124

99% 3136

100% 3287 (longest request)

你可能感兴趣的:(基于PHP客户端的TokyoTyrant(TCH, TCB, TCT), Memcache, Mysql性能测试)