设为首页 收藏本站
查看: 850|回复: 0

[经验分享] MongoDB集合结构分析工具Variety

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2016-3-23 09:31:47 | 显示全部楼层 |阅读模式
项目地址: https://github.com/variety/variety


对于MongoDB这种schema-free 的数据库来说,存在数据库里的每一条数据在结构上经常不同,时间长了我们可能就很难去了解库里数据的具体结构了。今天分享一个叫Variety的小脚本,用于对collection中存储的数据情况进行分析。



Variety就是一个js脚本,直接使用mongo客户端执行。


一个简单的示例



创建一个集合:
1
2
3
4
5
   
db.users.insert({name: "Tom", bio: "A nice guy.", pets: ["monkey", "fish"], someWeirdLegacyKey: "I like Ike!"});   
db.users.insert({name: "Dick", bio: "I swordfight.", birthday: new Date("1974/03/14")});   
db.users.insert({name: "Harry", pets: "egret", birthday: new Date("1984/03/14")});   
db.users.insert({name: "Geneviève", bio: "?a va?"});   
db.users.insert({name: "Jim", someBinData: new BinData(2,"1234")});



让我们用这个脚本分析下:
1
   
$ mongo test --eval "var collection = 'users'" variety.js

+------------------------------------------------------------------+
| key                | types              | occurrences | percents |
| ------------------ | ------------       | ----------- | -------- |
| _id                | ObjectId           |           5 |    100.0 |
| name               | String             |           5 |    100.0 |
| bio                | String             |           3 |     60.0 |
| birthday           | String             |           2 |     40.0 |
| pets               | Array(4),String(1) |           5 |     40.0 |
| someBinData        | BinData-old        |           1 |     20.0 |
| someWeirdLegacyKey | String             |           1 |     20.0 |
+------------------------------------------------------------------+

(“test”是我们分析的集合所在的数据库)


看起来每个人都有一个“name”和“_id”。大多数,但不是所有人有“bio”。


有趣的是,“pets”可以是array或者string,但是array比string多。这会在应用程序中导致任何问题么?


上面命令就是在test加的users这个collection上进行数据结构分析。


从上面结果我们能够看出,Variety将所有在users中出现过的字段都进行了统计,包括其类型和数量,以及出现在记录中的频率。这对于我们了解一个collection中的数据是很有用的。比如我们可以很容易看到是否在应该是数字的字段上还出现了一些string类型的值。如果是的话,可能要检查一下代码中是否有类型问题。


似乎创建的第一个文档有一个奇怪的遗留键值 -- 那个构建这个属性类型的蠢蛋没有在之后清理掉。如果有数千个早期的文档,我会参阅基础代码去确认它们不再使用,然后全部删除它们。那样就不会让之后的开发者困惑。


结果存储在varietyResults数据库用于之后的使用。



当分析花费很长时间时查看进度



查看日志尾部是很好的方法。MongoDB为你提供了“完成百分比”的度量。这些操作对于巨大的集合会花费很长时间。



只分析当前的文档


也去你真的有一个非常巨大的集合,你不能一整天一直等着Variety的结果。


也许你想忽略集合的最老的文档,只想看看集合的文档结构是怎样的。


可以应用“limit”约束,只分析集合中的最新文档,像这样:  
1
   
$ mongo test --eval "var collection = 'users', limit = 1" variety.js


让我们更加接近的检查结果:

+----------------------------------------------------+
| key         | types       | occurrences | percents |
| ----------- | ----------- | ----------- | -------- |
| _id         | ObjectId    |           1 |    100.0 |
| name        | String      |           1 |    100.0 |
| someBinData | BinData-old |           1 |    100.0 |
+----------------------------------------------------+


我们只检查了最后一个文档(“limit = 1”)。它属于Geneviève,只包含_id,name和bio列。因此只有这三个键是合理的。



分析文档到一个最大深度



也许你可能有一个非常深的嵌套对象架构,而你不想深入分析到到一定深度。


可以应用“maxDepth”约束,限制深度,Variety将循环查找以找到新对象。  
1
   
db.users.insert({name:"Walter", someNestedObject:{a:{b:{c:{d:{e:1}}}}}});


默认将会一直深入到架构底部:
1
   
$ mongo test --eval "var collection = 'users'" variety.js


+----------------------------------------------------------------+
| key                        | types    | occurrences | percents |
| -------------------------- | -------- | ----------- | -------- |
| _id                        | ObjectId |           1 |    100.0 |
| name                       | String   |           1 |    100.0 |
| someNestedObject           | Object   |           1 |    100.0 |
| someNestedObject.a         | Object   |           1 |    100.0 |
| someNestedObject.a.b       | Object   |           1 |    100.0 |
| someNestedObject.a.b.c     | Object   |           1 |    100.0 |
| someNestedObject.a.b.c.d   | Object   |           1 |    100.0 |
| someNestedObject.a.b.c.d.e | Number   |           1 |    100.0 |
+----------------------------------------------------------------+

1
   
$ mongo test --eval "var collection = 'users', maxDepth = 3" variety.js


+----------------------------------------------------------+
| key                  | types    | occurrences | percents |
| -------------------- | -------- | ----------- | -------- |
| _id                  | ObjectId |           1 |    100.0 |
| name                 | String   |           1 |    100.0 |
| someNestedObject     | Object   |           1 |    100.0 |
| someNestedObject.a   | Object   |           1 |    100.0 |
| someNestedObject.a.b | Object   |           1 |    100.0 |
+----------------------------------------------------------+


如你所见,Variety只是深入了三层。



分析一个文档子集



也许你有一个巨大的集合,或者你只关心文档的某个子集。


你可以应用“query”约束,使用了一个标准的MongoDB查询对象,在分析前过滤需要的文档子集。  
1
   
$ mongo test --eval "var collection = 'users', query = {'caredAbout':true}" variety.js



输出为JSON易于提取和解析



Variety支持两种不同的输出格式:  
    . ASCII:很好格式化的表   
    . JSON:有效的JSON结果用于随后其他工具的处理


默认格式是ASCII。你可以通过提供给Variety的属性outputFormat选择格式类型。有效值为ascii和json。
1
   
$ mongo test --quiet --eval "var collection = 'users', outputFormat='json'" variety.js


Quiet选项



MongoDB和Variety输出一些额外信息到标准输出。如果你想移除这个信息,你可以使用--quiet选项提供给mongo可执行命令。Variety也可以读取这个选项并减少不必要的输出。同时连接outputFormat=json时是非常有用的。你会只收到JSON,不带有任何其他字符。
1
   
$ mongo test --quiet --eval "var collection = 'users', sort = { updated_at : -1 }" variety.js



辅助成员读取



在一个繁忙的复制集主成员上分析可能花更长时间比从一个辅助成员读取。为了从辅助成员读取,我们通过设置slaveOk属性为true来告诉MongoDB执行辅助成员读:
1
   
$ mongo secondary.replicaset.member:31337/somedb --eval "var collection = 'users', slaveOk = true" variety.js



在MongoDB保存结果用于以后使用



默认,Variety只打印结果到标准输出并不存储它们在MongoDB。如果你想自动保存它们在MongoDB用于之后的使用,你可以设置参数persistResults。Variety然后存储结果文档到数据库varietyResults,集合名源自原集合名。如果源集合名是users,Variety将在varietyResults数据库下以集合名usersKeys存储结果。
1
   
$ mongo test --quiet --eval "var collection = 'users', persistResults=true" variety.js


保存到另一个数据库,你可以指定以下参数:  
    . resultsDatabase -- 存储Variety结果的数据库。接受数据库名或者一个host[:port]/database链接地址。   
    . resultsCollection -- 存储Variety结果的集合。警告:在结果插入前该集合删除。   
    . resultsUser -- 结果数据库的用户名   
    . resultsPass -- 结果数据库的密码
1
   
$ mongo test --quiet --eval "var collection = 'users', persistResults=true, resultsDatabase='db.example.com/variety' variety.js


需要注意的是,Variety在对数据结构进行分析的时候,实际是用MapReduce来做的,会进行全表扫描操作,所以如果是对线上库进行分析,那么建议最好使用一个不提供服务的备份库或者在业务低峰来做。避免给线上业务造成压力。




运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-194560-1-1.html 上篇帖子: MongoDB报表实例 -- 隐藏成员方案 下篇帖子: MongoDB介绍
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表