V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Newyorkcity
V2EX  ›  问与答

请问各位从数据库 SELECT *拉到程序内存里的数组,如何保证删除元素的无误和高效?

  •  
  •   Newyorkcity · 2020-01-22 12:55:26 +08:00 · 1639 次点击
    这是一个创建于 1792 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有一个学生表,主键 id 是 int,对应的 java 里的数据实体里的 id 成员变量也是 int。

    再这样一个 mybatis 接口

    @Select("Select * from students")
    List<Student> getAllStudents();
    

    然后程序就能通过这个方法获得这个数组,就叫它studentList吧。。

    现在要实现响应前端按退学按钮,退学对应学生的功能。修改数据库是很简单的。但调整程序内存中的 studentList,删除对应的学生这件事上我有点困惑,想请问各位在实际项目中是如何做的?

    =======以下内容是自己一些想法,以免伸手党之嫌=========

    第一种: 前端返回的如果是 Student.id (在数据库和实体对象中均是 int ),也就是数据库学生表中的主键字段的值,由于之前可能已经有删除过(即之前的删除让数据库中的主键字段值不是连续的),故直接studentList.remove(id)显然不妥。

    那干脆,遍历 studentList,比较主键值,直到碰到对等的那个,然后用这个时候计数器i的值来studentList.remove(i)

    第二种: 不真正地在数据库中删除这条记录,而是添加一个enable之类功能的字段,所谓的删除只是把 enable 设为 0 或者 false。

    但这样的话,随着表渐渐增大,特别是其中被删掉的记录越来越多,程序就不得不带着大量无用数据在跑。同时返回给前端以供前端展示的时候,发过去的数据里这种无效的记录也很多。

    第三种: 数据库里的删除仍然是真的删除,但不让前端返回 Student.id ,而是让前端在展示前根据 Student.id 排序,然后按下按钮提交上来的数据不是 student.id ,而是 student.index,也就是对应的 student 对象在数组的位置。这样借助数组的有序性,就能直接studentList.remove(index)了。。

    但这个方法的问题在于,网页展现的数据如果是旧的,在这个旧的网页上让一个同学退学前,别的管理员已经让一个同学退了学,那可能会导致这次退学退了个不相干的人,想想还有点牛逼。。。那这种问题要怎么解决呢。。

    谢谢

    8 条回复    2020-01-22 21:12:48 +08:00
    Raymon111111
        1
    Raymon111111  
       2020-01-22 13:31:51 +08:00   ❤️ 1
    让 id 是自增的, 用过的 id 不会再被用, 就不会出现那种删除-新增-删除的错误场景

    是不是要真的删除? 为了防止表无限增长, 可以这么干. 但是你可以算一下究竟会有多少数据. 如果不是特别多, 可以直接用 valid = 0/1 去判断是不是被删除的数据. 如果实在需要, 最好弄一个新的表记录这些被删除的数据, 以防后续想查而没有查的地方

    查的时候太多怎么办? 分页, 不要一次性全部拿出来.

    最后对于学生这种场景和具体的例子, 可以有些优化去加速查询(也避免上述数据无限增长导致查询慢的问题), 比如表里可以有入学时间, 去拿在校学生时可以拿入学时间大于某个时间点的那些, 这样历史数据就不会影响查询了.

    至于大表的问题, 定期归档比如十年前的学生就好了.
    registerrr
        2
    registerrr  
       2020-01-22 13:33:45 +08:00   ❤️ 1
    大哥硬盘不值钱的,现在做硬删除的很少了吧.
    硬删除重建索引,还浪费性能呢你不也得考虑考虑?
    shenlanAZ
        3
    shenlanAZ  
       2020-01-22 13:39:19 +08:00   ❤️ 1
    为啥要这么做?

    你删掉某个数据之后需要刷新表格 重新查询的。

    重要的数据是要做假删除的( isDel ),查询的时候带上条件 and is_del = 0.
    kawowa
        4
    kawowa  
       2020-01-22 13:40:22 +08:00   ❤️ 1
    数据库查询不做过滤是错误的做法,至少的至少也要做数据库分页查询
    前端请求:
    分页大小,当前页码,搜索关键词
    后端返回:
    当前页码,数据总数,分页大小的 List
    EminemW
        5
    EminemW  
       2020-01-22 14:01:04 +08:00 via iPhone   ❤️ 1
    你为什么会有这种问题?你删掉一条记录,就重新查一遍啊,为什么要一直用那个 list
    Newyorkcity
        6
    Newyorkcity  
    OP
       2020-01-22 15:21:52 +08:00
    @Raymon111111
    @registerrr
    @shenlanAZ
    @kawowa
    @EminemW

    感谢几位解答!
    ipwx
        7
    ipwx  
       2020-01-22 15:27:04 +08:00
    XYProblem
    msg7086
        8
    msg7086  
       2020-01-22 21:12:48 +08:00
    studentList.remove,找到主键对应的记录删除就行了。
    你一页才多少数据,我算你想不开一页放一万个学生的数据吧,一万条记录遍历查询主键要多久?能用得掉几毫秒吗。

    如果真介意这几毫秒,那就开个哈希表做索引就行了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1005 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 20:18 · PVG 04:18 · LAX 12:18 · JFK 15:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.