OSCHINA 问答合集[5]:8012年了,想用 MongoDB 取代 MySQL 可以吗?

局长 发布于 2018/09/17 23:25
阅读 5K+
收藏 29

开源中国问答区新栏目“OSCHINA 问答合集”上线啦,本期收录了 8 月高热度的问题及回复(吐槽),希望能让你有所收获~!

进入问答区:

你可以在技术问答版块畅聊技术
你可以在职业生涯版块寻道解惑
你可以在IT大杂烩版块和大家谈笑风生

我们希望:

这里可以成为一个能让大家有所收获的地方。因此,这里拒绝攻击、拒绝谩骂、拒绝无脑黑。
这里可以沉淀大家各种的技术问题。无论是新手的基础问题,还是资深开发的深度问题,都是有价值的。
这是一个更纯粹讨论技术的地方,能给程序员提供一片友好交流的清净之地,不懂的可以在这里寻找帮助,懂的可以在这里帮助别人。

总之,

在这里你可以向所有人提问。
反正你的问题可能会没答案。;-)

这期的技术问答内容相当丰富且详实,代码、配图该有的都有了,绝对是高质量的问答,废话不说,各位继续阅读吧!

==========分割线==========

开源中国技术问答

@双人鱼XKQ:酒店预订,飞机票预定的时候,每个日期对应一个价格,是如何实现的?

问题:预定酒店的时候,选择预定的时间,有的会直接在时间下方标明该日期房间的价格,不同的日期对应不同的价格。具体这个业务逻辑如何实现?

方案1:设置365天的每一天的价格(太累)
方案2:在获取时间的时候,根据价格规则进行获取,比如说我平时的价格设置为100,国庆节的价格设置为500,在获取价格的时候,根据价格规则中设置的进行获取。

现在能想到的方法就是这些了,也是请教别人获取到的方案,希望有做这方面的朋友多多指点。

>>>wxk_java
当初做过酒店预订的项目说下,方案也就是楼上所说的方案一:
房源价格设定默认价格,如需特殊价格后台设定开始-结束日期价格放到一张新表然后遍历,做好状态码 房源可能有锁定等等状态。
也不觉得比较麻烦

>>>lgwait
一般来说采用方案一,酒店方面有个名词叫日历房,每天的价格设置灵活,想改哪天就改哪天,光有价格还不行,还要有剩余房间数量,机票数据,一般是通过接口获取,做缓存,每时每刻舱位剩余座位都会变化的

>>>tinyhare
我觉得看需求方的要求,需求方要求设个默认价格,下单提前M天是N的优惠不就自动算了,再给配置手工指定价格。如果需求方就要指定每天的价格,那就提供个快速配置的方案,选中时间范围批量设置价格。我觉得完全看定价策略:逻辑生成的就做好逻辑,手工指定的就做好方便操作

>>>氪金
方案1,但你可以提供设价工具,比如可以直接设一年的标准价,然后把特价时段拿出来单独设价,以特价为最高优先价格

>>>木有文化
并不是方案一,举个例子,9.1号买10.1号的和10.1号买10.1号的,价格完全不一样,
可以参考航空的运价系统,,

>>>魔力猫
方案1不累,没人规定你必须天天写。这个只是数据库记录的结果。而结果的处理过程只需要你填写一个时间区间,然后写上价格。系统循环插就是了。

@踏破铁鞋无觅处:慢 sql 和多次 sql 查询那个好?

今天为了实现一个功能,光sql语句写了五六十行,每次修改sql的时候,也会想半天,感觉sql写的很复杂。
那么对于复杂的功能,多次查询后整合好,还是一个sql查询出来好呢?(查询结果是多条数据)

>>>飘摇清风
似乎不同的行业不同的应用要求不一样吧?我做的应用是超大数据量,但一插入变化就不大的,一般是拆成多条sql查询出来拼装。因为数据变化不大,数据一致性问题比较小,也不会因为数据量太大而长时间锁表。如果你的应用对数据一致性要求很高如财务、网上商城的库存之类的,感觉还是一条sql搞定好点,不然查询了一部分后,前面查询的数据又变了,数据就不太一致了。
PS:我因为一条大sql查询把服务搞死过。。。

>>>sxgkwei
飘摇清风 说的业务场景非常有道理,所以你得先考虑业务场景是否有强一致性要求。其次,大多数情况下,我觉得一个一个查出来整合会效率更高。原因如下:

1.你能问这个问题,一般认为就是页面展示查询。那么为了完成整体目标而分次查询,总次数也不会太多。
2.分次查询,有利于数据库自动使用到索引,会提高查询效率
3.一般单表查询,对于业务系统和 orm 框架来说,很多是有缓存的,其实查的是缓存,效率更高,而多表联合查询,一般会禁用这个级别的缓存(因为缓存了可能因为其它位置修改其中一个表的数据而导致缓存更新不了,导致查询出错误数据),就会导致联合查询更慢。
4.联合查询的sql语句,大多数在查询语法过程中,总数据处理量会变成多表的乘积。总处理数据量是 n*m*...,那么根本就快不起来。而单表查几条,参与运算的数据量就是主数据加几条关联数据。

综上,在大多数情况下,实际上关联的复杂 sql 查询,在整体应用层面,会是个差劲的选择。

>>>melon_jj
如果数据量小的话基本没有区别。
一次查询的优点是只需要一次连接,数据库查询的时候,连接是个耗时的操作。缺点是如果两个表数据多,则中间结果集太大,需要较多的内存资源。
多次查询的优缺点和一次查询正好反过来。另外多次查询也可以在程序中对每一次查询的中间结果做处理,这是一个灵活性。如果数据量大的话,多次查询要快一些,相当于是用空间换时间,如你上述所说,拼装sql会比较麻烦,但带来的是效率的提升,我认为还是值得的。如果表中建立了大量的索引的话,索引的命中率也很高。效率也会大幅提升。
>>>蓝水晶飞机: 补充一下:
1.其实平常有连接池复用,不会有太多明显的多次连接开销;
2.在我做的系统里面,背慢锅的都是JOIN
3.其实在ORM框架来看,JOIN产生了中间结果,竟不是A也不是B而是AB混合体,因此缓存怎么搞(不用缓存了)所以问题3还是各查个的吧然后在应用里面进行数据处理。
4.有缓存就是吊,不服数据库你自己做啊。 

>>>aruis
sql里面用上with,可读性可以大大提高,所以sql的维护成本并不一定比在程序里拆成多步实现要高。
至于用不用得上索引,岂可一概而论,这要看sql的写法跟表设计索引的具体情况。
直接武断下结论说用程序跑速度更快的,我觉得都不太可信。通常来说,sql写得够好,会比在程序里面算要快。因为数据库就是吃这碗饭的,要是group by还没有程序跑得快,岂不是人人都可以设计数据库了。
楼上有个老哥说的对,建议两种都试试,实践出真知。

@melon_jj:想用 MongoDB 取代 MySQL 可以吗?

有可能会出现哪些问题?

>>>lee_oschina
一是要看你的业务类型,二是不能用MYSQL的思路来建MONGO

>>>sxgkwei
适用场景不同,一般对事务性要求不强的领域,比较适合MongoDB。如果对一系列增删改有强制事务原子性要求,那显然要数据库支持事务回滚的啊,还是MySQL吧。
还有你得忍受一些小bug之类的,毕竟MongoDB发展时间没MySQL长,出个小坑也可以理解。或者你还得承受去年那种MongoDB数据泄漏造成的恶劣影响的损失之类的。其它的,就没什么了。

>>>乌龟壳
4.0 之后,理论上的替代已经成立了,核心机制已经支持事务。
实际我还没试过不知道情况。

不过最重要的一点楼主没说,为什么要换? 出于什么原因考虑?

@smallfatQQ:提取两个txt文件中有相同文字的那行数据,并以同样格式存储到另一个新的txt文件中

我有两个文件:一个文件叫list.txt里面包含n个id,每个id一行

ZINC042-03-483
ZINC268-95-155
ZINC036-51-026

一个文件叫data.txt里面包含有n多行(上亿行)的信息,其中有些行中包含了list.txt中的id信息,如下仅列部分数据:

123    ZINC268-95-155
2323    ZINC036-51-026
231    ZINC042-03-483
1    ZINC042-03-4444  
444    ZddCyyy
6326    dgag
32323    yyj
211    ddghghd
3546    ZINC036-51-026

我希望通过list.txt文件里的3个ID在data.txt文件查找相对应的信息,然后将data.txt中整行信息都输入到一个新的new.txt文件里。如果在list.txt中信息未在data.txt中查到,就在new.txt中仅显示list中的ID

热心的 oscer 几经修改终于解决了楼主的问题,建议大家点进原贴看看~
>>>tcxu

readStream1 = open("list.txt", "r");
context1 = readStream1.read();
a = context1.split('\n') # 从文档 list.txt 取得的关键词数组
size = len(a)
b = [ 0 ]*size # 对应关键字数组 a,创建一个整型数组 b,每个元素的初始值为零。
result = open("new.txt","w")
fo = open("data.txt", "r")
try:
  while True:
      line = fo.readline()
      if line:
           index= 0
           for v in a:
               if line.find(" " + v) > -1:
                   v = v + "  " + line
                   b[index] = b[index] + 1
                   result.write(v)
               index = index + 1
      else:
          break
finally:
    fo.close()

# 最后检查每个关键字是否在数据文档data.txt都有数据对应
index=0
result.write("\n")
for value in b:
    if value == 0:
        out = a[index]+"  NA     NA\n"
        result.write( out )
    index = index + 1
result.close()
readStream1.close()

list.txt

data.txt

new.txt

>>>公孙二狗
把 2 个文件的信息都先处理一下,按 ID 排序生成新的文件,然后对新文件再进行匹配比较
还有一种方式就是先导入数据库,使用多表关联查询导出数据

>>>sxgkwei
大量数据时,仅程序可能不太可能能实现。因为无论什么语言,就把这些数据载入内存,它也要消耗很大空间啊。所以,可以考虑使用数据库,逐行读取批量插入,先把数据都插入数据库两个表,然后,使用 sql 就能比对出你要的结果。

@laozhong__:阿里RDS一张200w的订单表,部分数据查询快,部分数据查询慢,求解?

查询字段是个datetime格式的create_time,有索引,全部都是按照主键id倒序排,如果去除id倒序排的话没有问题:
基本格式如

​​​​​​​SELECT * FROM `tb_orders` WHERE `create_time` BETWEEN '2018-01-21 00:00:00' AND '2018-01-21 23:59:59'  ORDER BY `id` DESC
1. `create_time` between '2018-01-21 00:00:00' and '2018-01-23 23:59:59' 耗时2.343s 结果集22099条
2. `create_time` between '2018-01-21 00:00:00' and '2018-01-21 23:59:59' 耗时2.390s 结果集8956条
3. `create_time` between '2018-07-21 00:00:00' and '2018-07-23 23:59:59' 耗时0.250s 结果集15403条
4. `create_time` between '2018-07-21 00:00:00' and '2018-07-21 23:59:59' 耗时0.015s 结果集5638条

给我的感觉,是1月份的数据量差不多,但是慢很多,7月份的快很多!其他月份也有快有慢!
表数据是187w多,40多个字段,pma显示大小为数据440MB,索引256MB,innodb引擎;
这会是什么原因呢!
explain如下,为何会有filesort :

EXPLAIN SELECT *  FROM `tb_orders`  WHERE `create_time`  BETWEEN '2018-01-21 00:00:00' AND '2018-01-21 23:59:59' ORDER BY id DESC


问题补充
// 1. 改用create_time排序,能解决查询慢的问题
// 2. 如果只查询id列,或者create_time列,速度快,没问题,我补充了profiling数据
/ 3. 我感觉现有的回答都没用很好的解释,1、4月份的数据慢,其他的快,当然17年的几个月就更加慢了,尽管量还少些!说缓存也对吧,但是这么点数据量,实在不应该啊!

>>>OSC_YIdCag

SELECT t1.* FROM `tb_orders` t1 INNER JOIN (SELECT `id` FROM `tb_orders` WHERE `create_time` BETWEEN '2018-01-21 00:00:00' AND '2018-01-21 23:59:59') t2 ON t1.id=t2.id ORDER BY t1.id DESC

>>>我叫金正恩
订单ID使用10位数的时间镞 加上固定位数的随机数
查询时候时间转成时间镞补0站位,根据ID卡范围,千万级别数据也是毫秒级查询 
自增ID卵用没有


模拟数据是2018-05-30至2018-10-05,共计11100040条
查询数据范围内任意一天 ,内网这个开发用的库比较繁忙0.42秒

>>>魔力猫
因为MySQL只能使用一个索引,已经用了createtime进行范围查询了,order 的又是另一个字段,索引无效。
接下来的速度其实就是看数据分布情况和内存情况了。日期近的,大概率也被别的业务调用,所以大概率内存有缓存。返回数量少或者正好当时内存比较空余,在内存中运算不使用或者少使用临时文件,就快一些。

@HaleyZhang:sql 优化通配符 % 不能放词首

优化中说%最好不要出现在词首,那应该怎么写查出包含hh的name呢?

>>>icytail

SELECT *
FROM car
WHERE INSTR(NAME, 'hh') > 0;

>>>魔力猫
​​​​​​​百分号这种通配符最好不要出现在开头的意思,是因为这样写,索引无法匹配,而不是不能这么写。这么写本身,是符合语法的,但是性能是否能满足你,就要看实际运行情况了。
百分号、问号,这样的通配符,如果只出现在结尾,普通索引可以扫描。如果只出现在开头,反向索引可以扫描。如果前后都有,那么索引就彻底凉了。

职业生涯问答

看看程序员关心的职业生涯问题都有哪些 ——

@老朽怕是要破戒了:公司给股份1%,但是要求降工资3000,强行想拉我上船,求指点

背景:初创公司,团队一二十人,二三线城市,公司股权结构大概是大boss 80% ,小boss 17, 还有一个小机构当初也投了10万块钱,占 3%,成立不到1年,当初大概总共投110万的样子,现在打算再投100w,目前公司肯定还是亏损的,主要是人员工资成本,公司发展方向个人感觉总体还行。

刚入职的时候,是以技术合伙人的角色应聘的,当时要求工资16.5K ,老板说要给期权,大概1%的期权,但是大概一年半之后才转股份,工资就压倒15K,当时勉强同意了,

这不才转正呢,公司表示对我的能力认可,怕我对当前工作不能完全上心,想拉我上船,已创业者的身份加入,说直接给我1%的股份,原先的期权不变,到时候期权到时间,一共2%的

但是说光给干股怕我没啥感觉,说需要放点血,所以,需要把我的工资压到12K
现在想问问我大佬们,这种情况,有没有什么好的建议和意见

>>>翔少
光给干股怕我没啥感觉,说需要放点血
狗屁理论,你就说没感觉不是因为没放血,而是因为干股不够多

>>>暗影风暴
以股份为由,限制薪资,限制自由的都是耍流氓,不尊重人的表现

>>>何勇杰
前面几个哥们都分析得很到位,股权是一种激励措施。公司合伙人降薪入股是对公司发展看好和投入的表现。别人其实也怕技术只拿钱不放血,到时候不能共患难,直接可以去下一个公司继续做技术拿钱。
愿不愿意放血,这个你其实需要多方面去分析的。你作为技术合伙人,看来公司的发展有很大部分是依赖于技术平台的好坏,那么你在公司经营过程中,参与了多少事务?如果大小事情你都知晓,与你工作相关的事务来一起讨论,并尊重你的意见。那么还是可以的。(避免在隐瞒你的情况下,公司负债,这个你需要共同背债的)另外还需要谈好,在什么条件下以什么形式来分红。因为你想做到上市再分红,那么你这个以股份得到收益风险系数会更大。
另外,对于技术最终只占股2%,确实是非常少的。不过好的做法就是算好目前的估值。不要赠予的方式,拿每个月工资的一定比例来购买股份。一般好一点10%股份左右,不过考虑到你前期创业没参与投入,不算创始人。个人做为技术合伙人拿到5%,应该算可以的。

以目前这种股份比例,加上口头上说是赠予,背后又要降薪的做法。就是表面上做的好看,结果觉得不划算,又要以共同奋斗为目标来降薪,这种做法就是忽悠的方式,个人觉得没有诚意。他为你着想的部分不足。

请他表示一点诚意!

>>>黑狗
这种你占了大便宜了
我觉得你应该这样,花1200块开一个公司,注册资金搞个200W吧,每个月花200块找个财务代账,估值200W,折价卖给他49%股份,只收他20W。你们还谈啥工资啊,你给他股份啊,他对你这么好你可不能亏了他

>>>newzai
不能明说拒绝, 否则你就在公司混不下去的。委婉一点拒绝,,这个时候,要哭穷,自己啥房贷啊,车贷啊,老婆,子女的生活费啊,每月开销到手的钱,基本精光,如果少点3000元,日子没法过了。
然后再说,,自己也想和公司一起发展。但是现实生活压力太大。。。

@OSC_GALyfe:去给政府做项目的公司好吗?

目前有两家公司可选 坐标西北地区,我是其他语言转java

几个公司和铁路合资 新创立的 “创业公司”,主要改造铁路老旧的物流系统做一个打通铁路物流信息的一个多联式运输信息平台产品,盈利方式未来企业付费使用这个物流信息产品,团队年轻只用新东西新技术Git、docker,工作环境也可以,但是自己带电脑,每个月补电脑费,加班可以回家做,因为铁总数据外网断开所以要连内网VPN。各种补助补贴多 固定每月800-1300元,交通不方便在开发区。

中科软,现在需要招兵买马,有大量项目, 要做好几年,在本地给zf做wei稳an防等项目,据说也是用新技术、新东西,版本用SVN,说有大数据,每周Google看板方式交流,但是我有点怀疑给zf做东西技术含量问题。电脑ThinkPad统一配,不能连公网,最好自己要准备个电脑网上下第三方包等,然后用光盘传文件。每月补贴较少,交通方便点,在市区。补贴只有餐补300,说是然后做项目功能做的多以后就拿的多。

两家薪资一样,铁总创业公司补贴多 薪资晋级规则明确,实发会多。 做项目公司没有明确的薪资规则,只是说多劳多得,可能会驻场,涉密电脑不能上网,下载更新包和第三方组件感觉不方便,没有这方面经验,然后就是工作环境不一样。大家给个意见

>>>随机9380fa
皮包公司,千万不要去。这个工作的性质就似一个包工头通过关系,拉到一个工地项目,然后拉一帮农民工去搬砖,包工头为了追求利润,就会不断叫民工加班加点去完成个工地项目,质量能用几年就行了,项目交付后包工头分了大钱,人员解散,工地出事故死人的话,包工头早就远在天边了。

>>>walykyy
真的不建议去政府企业,我就是刚辞职的,虽然是实施类的,客户要求真的多,随时都有可能要求改动,遇到有想法的你会觉得上天入地都没有门,根本就不可能实现,脾气不好的骂人跟骂孙子似的,我在铁路和政府财政干了11年多了

@IT菜鸟进山:一个什么样的工作环境适合人成长,对于技术人员来说?

行业方向感模糊,技术不知道怎么提升,但是闲下来又很慌,我该怎么办

>>>netkiller-
环境是自己创造的,不是别人给与的。
我十年如一日的,给自己设置目标,培养自己的兴趣点,不断打怪升级,才走到今天。

>>>暗影风暴
成长和环境有关,但并不是唯一,核心在自己。
不管什么样的公司都有可以学习的地方,就看这些点是不是自己渴望学习的罢了。
技术是工具,要么自己打磨(可能慢一些),要么有人领着你告诉你怎么打磨(快一些),但是这些归根结底都是自己打磨。
业务也是技术成长的一个不可或缺的发力点,要想扎根一个行业,业务不精那是不行的。
综上,关键是看自己对技术成长的看法和实际行动。公司环境只是一部分而已。希望对你有所帮助

>>>sxgkwei
一般来说,适合成长的公司,其实核心就一点:长期浸淫一个项目的开发。不管是互联网公司还是自主产品公司,一个人进去之后,都是在持续做一件事儿,这样才能锻炼深入思考各种套路的思维方式。

不适合成长的公司,当然就是反方向的:始终在换开发的项目。外包,接项目来做2/3月完工的,或者不是外包但把你派到各个客户现场去2,3个月给客户开发完一个项目的。核心就是短期项目,这种项目一般只能 CRUD 下数据库,ctrl+c/v 了,没人在乎谁离开,公司内部也不在乎各种写法的优化与效能。所以去了就是码畜。

>>>岑臣
整个公司几十号人,十个产品,八个运营,七个客服,一个总监,两个老板,就你一个程序员!前后左右上下各端都等你来写!你每天都要面对各种突发情况,需求多到你做不完,而且随时有重构风险的环境!

>>>南山北寺
工资高到你舍不得走,还有一群傻逼队友嗷嗷待哺的环境。

你也希望自己的提问/回答上榜?欢迎大家前往>>>技术问答区,多多提问,多多回答~!
遇到技术问题,就上开源中国问答区

==========分割线==========

OSCHINA 问答合集[1]:老大竟然说我不会写 SQL ……
OSCHINA 问答合集[2]:我有一套高峰期每秒钟约有 1 万人下单的系统,遇到了关于 Java 高并发的问题
OSCHINA 问答合集[3]:无法确定自己的方向,又无法转行怎么办?
OSCHINA 问答合集[4]:入职一个月发现公司项目代码管理乱、代码烂,该留还是走?

加载中
1
qnloft
qnloft

额,标题党~!进来一看全是mysql的内容~~~~~

不过话说回来了,还是mysql好用~!mongo局限性太多.....

1
idisikx
idisikx

本人渣渣说说看法。

mongodb能做的mysql都能做,相反mysql能做的mongodb很多做不了,而且mongodb连基本的事务都没有。

性能上的差距mysql配上redis做缓存就可以了。

墨子Zhai
墨子Zhai
mongodb没事务, 发言前先到官网去看一下,别乱说啊。
1
-TNT-
-TNT-

正在用mongodb的路过…4.0也支持多文档的事务了

项目早起用mongodb可能更好吧,sql数据库重构起来还是疼

1
刘少
刘少

目前mongodb 单表7亿,索引建好了,性能还是刚刚的。

1
至少20个字符
至少20个字符

%那个,我试了一下第一个老哥用的

SELECT *
FROM car
WHERE INSTR(NAME, 'hh') > 0;

这个方法,我实际测试比我用 like ‘%hh’查询慢了0.2秒,在有索引,数据量94万的情况下

至少20个字符
至少20个字符
但是速度只比 like '%hh%'慢了0.06S
0
Elric黄
Elric黄

当年用mongodb做了一个商城,当时还是2.0左右,做完就后悔了,从此不敢再用mongodb,一直用着mysql

0
Zzzzzzzz神
Zzzzzzzz神

我怎么感觉mysql就像php一样,什么鬼都想来取代它

0
小王来了
小王来了

想用就用 没有什么不可以

返回顶部
顶部