• 请不要在回答技术问题时复制粘贴 AI 生成的内容
lux182
V2EX  ›  程序员

应该使用 select * 吗?

  •  
  •   lux182 · Aug 4, 2020 · 10318 views
    This topic created in 2285 days ago, the information mentioned may be changed or developed.

    在使用同样索引,同样需要回表查询的情况下,应该使用

    1. select * 还是 2. select 字段,字段,...

    我能想到的使用后者的优点可能就是节省那么一点点带宽,

    缺点是极大的影响开发效率和维护难度,并且 mapper 文件难看,难懂

    72 replies  •  2020-08-06 09:23:11 +08:00
    chenset
    chenset
    Aug 4, 2020
    1
    1.特别需要注意性能与并发或者大 text 字段的时候就列出字段

    2.其他情况直接*

    两者不误
    clf
    clf
    Aug 4, 2020
    2
    现在大部分 select 操作应该都是 orm 框架帮我们处理了?

    对于少数的自己写的查询,我一般都是 select 字段,字段,字段 这样对应自己定义的对象来处理。(反正都是用 navicat 的查询构造器来写的,勾选一下参数的事情,不需要特别麻烦。
    lux182
    lux182
    OP
    Aug 4, 2020
    3
    @chenset 同意,现在市面上好多不分青红皂白都建议列举所有字段
    lux182
    lux182
    OP
    Aug 4, 2020
    4
    @lychs1998 我感觉最近几年项目用 orm 反而少了。用工具构造查询是挺方便,缺点就是每次修改数据库就要在代码里 review 一遍。而且字段列举很多让人看的不舒服
    piecehealth
    piecehealth
    Aug 4, 2020
    5
    遇到过一次玄幻的事,用的 PostgreSQL 9+,select 字段...(字段不全是索引列) 跟 select * 用的索引不一样( pg 没法指定索引),select * 用的是效率高的索引。
    cruii
    cruii
    Aug 4, 2020
    6
    我觉得把字段写清楚更好看,能让别人清楚的知道,你想拿哪些数据。
    CrazyEight
    CrazyEight
    Aug 4, 2020
    7
    select *用不到索引覆盖,而且字段过多会占用更多的 joinBuffer 会导致表连接变慢
    lux182
    lux182
    OP
    Aug 4, 2020
    8
    @piecehealth select * 会有索引优化器选择合适的索引吧?
    lux182
    lux182
    OP
    Aug 4, 2020
    9
    @cruii 当字段只有 3 、5 个时候比较清楚,当字段 10 多个以上时候,我觉得不如我直接看 model,还有注释呢
    lux182
    lux182
    OP
    Aug 4, 2020
    10
    @CrazyEight 已经说明了不考虑覆盖索引,实际情况覆盖索引使用的字段也很少,基本不超过 3 个。joinBuffer 这个触及知识盲点
    Vegetable
    Vegetable
    Aug 4, 2020
    11
    不推荐 select * ,不是因为性能问题,而是你没法控制 * 代表了什么,你的代码有可能会依赖数据库结构而不自知。
    lux182
    lux182
    OP
    Aug 4, 2020
    12
    @Vegetable 可以举个例子吗?
    xuanbg
    xuanbg
    Aug 4, 2020
    13
    一般都是*,特殊情况列出字段
    InkAndBanner
    InkAndBanner
    Aug 4, 2020
    14
    还是写清楚更好 用啥拿啥
    lux182
    lux182
    OP
    Aug 4, 2020
    15
    @xuanbg 我也是这样用的。接触的传统型公司反而是列出字段的居多,比如恒生,他们会用工具生成一系列 mapper,service,里面各种条件表达式。说实话还不如自己写
    stabc
    stabc
    Aug 4, 2020
    16
    我一般是排除比较大的字段,但是 SQL 语句目前没法简单的排除字段
    ragnaroks
    ragnaroks
    Aug 4, 2020
    17
    手动查询用"*",代码里面指定字段,因为有自动步枪
    yuanbo6
    yuanbo6
    Aug 4, 2020
    18
    前一阵看了一个文章说还是推荐带字段,原因太长我给忘了……
    yc8332
    yc8332
    Aug 4, 2020
    19
    这个要看吧。。如果没差几个字段,又不是大字段。。无所谓
    superrichman
    superrichman
    Aug 4, 2020 via iPhone
    20
    在我这里你敢用 select *会被打死的 /doge
    meeop
    meeop
    Aug 4, 2020
    21
    我的原则是在性能不是问题时注重开发效率,性能有问题在考虑优化
    绝大多数场景性能都不是问题,所以放心用 select * 除非是有 orm 帮你生成
    Jackeriss
    Jackeriss
    Aug 4, 2020 via iPhone
    23
    *能不用就不用,就像 import *一样,谁知道你的*里有什么?
    Jooooooooo
    Jooooooooo
    Aug 4, 2020
    24
    如果是真的要捞出全部字段就用

    数据库对 * 有专门的优化
    vindac
    vindac
    Aug 4, 2020
    25
    额,我们又上百个字段的表从其中取五六十个,都是 select *
    lolizeppelin
    lolizeppelin
    Aug 4, 2020
    26
    不说其他的 一旦你数据库表字段有增加,所有对这个表 select*的代码部分都要改

    如果只是写点小东西, 无所谓
    lux182
    lux182
    OP
    Aug 4, 2020
    27
    @superrichman 所以啊,你的原因是?
    VictorJing94
    VictorJing94
    Aug 4, 2020
    28
    不应该,虽然我经常用,数据库栏位变动会导致*到的数据不可控
    lux182
    lux182
    OP
    Aug 4, 2020
    29
    @lolizeppelin 字段增加,增加 model 字段不就可以吗?
    lux182
    lux182
    OP
    Aug 4, 2020
    30
    @VictorJing94 这里可控是为了什么?作为底层 service 在对外暴漏的时候还有一层转换的啊
    lolizeppelin
    lolizeppelin
    Aug 4, 2020
    31
    @lux182

    新字段不在最后一行的时候,你 model 全乱

    遇到需要热更需要先升级数据库,再慢慢升级程序的时候,你 select*咋搞
    lolizeppelin
    lolizeppelin
    Aug 4, 2020
    32
    @lux182

    如果你只想抬杠,或者就是要说 select*好,那么你赢了

    如果不是,我建议你多看看大型项目,好好理解下那些看上去多余的做法
    很多做法在小项目里是不需要的,大型项目周期长迭代多,很多看上去东西都是为了解决版本迭代更新兼容

    你随手写点东西,压根就不用考虑迭代更新兼容,甚至不用考虑单元测试
    自然很多做法就是多余的,禁止 select*就是基础中的基础
    wuketidai
    wuketidai
    Aug 4, 2020
    33
    显示优于隐式
    brader
    brader
    Aug 4, 2020
    34
    @lux182 字段增加,增加 model 字段不就可以吗?
    我想你对这里有个狭隘的误会,不同语言中,是有不同表现的,对于一些语言,数据库增加字段,是不需要去代码的 model 增加字段的。
    admol
    admol
    Aug 4, 2020❤️4
    35
    想象一个场景, 你有一个接口, 每秒有非常多用户的来请求, 你后面的逻辑涉及到数据库语句写的是 select * ; 平时这可能没有任何问题, 但是有一天产品需求发生变化, 你的数据库需要添加一个字段, 并且这个字段需要返回, 请问你应该怎样来开发这个功能并上线?
    先上数据库 DML 语句还是先上你的代码?
    如果先上数据库, 你线上代码还是老的, 还没有那个新的字段, 代码全是 select * , 而你与之对应的 model 肯定是没有这个字段, 如何与它映射? 是否会报错? java 的 mybatis 至少会.
    如果先上代码, 加入你有 10 台服务器呢, 代码上线, 请求进来之后全是找不到新字段.

    如果之前你这个表涉及的 SQL 语句全部都是指定字段 select c1,c2,c3 from table , 那你就可以放心大胆的先让 DBA 给你添加表字段, 然后慢慢上线你的服务, 这部分至少不会有什么问题
    hello826
    hello826
    Aug 4, 2020
    36
    那为啥阿里的 java 开发手册,第五章 Mysql 数据库,第三小节 sql 语句
    [强制] 不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 SQL92 定义的标
    准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
    这个 mysql 实战也是推荐使用 count(*)
    dddd1919
    dddd1919
    Aug 4, 2020
    38
    如果需要所有字段,区别不大。
    如果只需要部分列的话最好显示声明要返回的字段,省带宽性能更好使用稳定。
    显示声明字段还有个好处就是如果字段全部在索引中,可以直接从索引返回结果
    WaldenHorizon
    WaldenHorizon
    Aug 4, 2020
    39
    开发时间特别紧用*,否则好好写
    MeteorCat
    MeteorCat
    Aug 4, 2020 via Android
    40
    大表筛选不要用,小表筛选可以用;开发阶段尽量用*,正式验收尽量不要用*;
    有时候项目需求文档很多版本,这样加个*直接获取比较方便
    panhongx
    panhongx
    Aug 4, 2020
    41
    @hello826 你好像审错题了
    gz911122
    gz911122
    Aug 4, 2020
    42
    @lolizeppelin 跟顺序有什么关系啊?
    lux182
    lux182
    OP
    Aug 4, 2020
    43
    @lolizeppelin
    @gz911122 没遇到影响顺序的场景
    lux182
    lux182
    OP
    Aug 4, 2020❤️1
    44
    @lolizeppelin
    ”新字段不在最后一行的时候,你 model 全乱“ ,这点我一直没遇到过,你的场景是什么啊,用的什么框架?
    ”遇到需要热更需要先升级数据库,再慢慢升级程序的时候,你 select*咋搞” ,这种情况也是比较常见的,我们也经常先更新数据库,后上程序的。所以还是不知道你的场景。
    所以你说的这几点没有说服力。
    lux182
    lux182
    OP
    Aug 4, 2020
    45
    @brader 不是语言的问题,而是框架设计问题。我看过一些 python 程序员喜欢直接拿数据库 map 结果返回前端
    lux182
    lux182
    OP
    Aug 4, 2020❤️2
    46
    @admol “如果先上数据库, 你线上代码还是老的, 还没有那个新的字段, 代码全是 select * , 而你与之对应的 model 肯定是没有这个字段, 如何与它映射? 是否会报错? java 的 mybatis 至少会.”
    我使用过程中,这种情形很多,mybatis 不会报错的
    lolizeppelin
    lolizeppelin
    Aug 4, 2020
    47
    @lux182
    那我知道了
    框架里 map 字段,压根就不需要你关心是 select*还是 select 字段
    wakzz
    wakzz
    Aug 4, 2020
    48
    单单考虑业务的问题,也不建议用 select *,因为一旦业务变更数据库新增字段,就会导致线上程序 sql 映射错误,不好向前兼容。
    gz911122
    gz911122
    Aug 4, 2020
    49
    @wakzz 新增字段无影响吧?
    为什么会导致映射错误呢?
    VictorJing94
    VictorJing94
    Aug 4, 2020
    50
    @lux182 楼下说清楚了.......应该不需要我再重复了吧
    useben
    useben
    Aug 4, 2020
    51
    看查询的索引类型, 不同不同处理
    wangbudong
    wangbudong
    Aug 4, 2020
    52
    没有性能问题的情况下,也就是不会导致 io 阻塞的情况都可以用 select * ,至于说啥迭代,数据库和 entity 的关系处理好了,只需要改 entity 和数据库,不用 orm 也可以
    1069401249
    1069401249
    Aug 4, 2020
    53
    谁用 select *我直接打死,占 io 内存,大列表的时候 select*有几次导致内存爆掉了
    akira
    akira
    Aug 4, 2020
    54
    小项目随便你怎么写都行。 稍微有点量的项目 还是别用 select *了,回头逐个地方修改还是挺麻烦的
    realpg
    realpg
    Aug 4, 2020
    55
    结合实际,没有一杆子打死。
    性能,吞吐,负载综合考虑。
    CEBBCAT
    CEBBCAT
    Aug 4, 2020 via Android
    56
    谢邀,Golang 选手,SQL 手写
    DelayNoMay
    DelayNoMay
    Aug 4, 2020
    57
    用 * 的话,数据库新增一个字段就报 scan error 了
    blockmin
    blockmin
    Aug 4, 2020
    58
    测试的时候数据都是几亿条,用 select * 的话下游团队会砍死我们的
    crclz
    crclz
    Aug 4, 2020
    59
    事务类的操作,用 ORM,例如 SpringDataJpa 的 repository
    查询类的操作,用 select*,外加 ModelMapper ( java )或者 AutoMapper ( c#)之类的工具.

    对于大字段,请将表拆分。
    woshipanghu
    woshipanghu
    Aug 4, 2020
    60
    说实话 你写的严谨一点那是不用*
    实际开发的时候用*没什么问题 不要有敏感字段暴露出去就行
    大部分项目不会因为加了*或没加*产生太大的影响
    读写多的几张表自然会想着去优化
    CrazyMoon
    CrazyMoon
    Aug 4, 2020
    61
    这要看相关代码的动态能力。
    另外如果是列数据库,基本不能用它。
    stevenkang
    stevenkang
    Aug 4, 2020
    62
    个人项目:select * —— 毕竟增减字段方便,自己的需求自己明白,只要快就行。
    公司项目:select 字段 —— 毕竟产品不来需求,字段绝笔不会去改,改起来费时间慢点就慢点,只要稳就行。
    keenkiller
    keenkiller
    Aug 4, 2020
    63
    单表查询一般都是 orm,join 的时候你跟我说你用 select *?

    不过做动态 sql 的时候只能用*,因为连表名都是动态传进来的。
    chihiro2014
    chihiro2014
    Aug 5, 2020
    64
    其实可以去看看 CMU 数据库系统这块的 SQL 优化和索引部分
    https://www.bilibili.com/video/av85655193
    saberlong
    saberlong
    Aug 5, 2020 via Android
    65
    代码上没碰到问题是因为用 orm 之类有映射功能的。原始的方式是和查询列顺序有关的。直接写*会导致这部分业务逻辑错误。写明列则只需修改需要增加列的地方。一个人了解所有项目是不可能的,允许随意使用*。那么发布时,可能就碰到惊喜。
    hxy91819
    hxy91819
    Aug 5, 2020
    66
    在关注性能的业务场景下,任何情况都严禁使用。
    lux182
    lux182
    OP
    Aug 5, 2020
    67
    @1069401249 上面还有一个也这样说,"把 xxx 打死",我想你是做领导做久了吧。
    okjb
    okjb
    Aug 5, 2020 via Android
    68
    跟使用场景有关。我自己私人查数据爱用检索全部字段。业务场景就检索特定字段。又说了一堆废话
    no1xsyzy
    no1xsyzy
    Aug 5, 2020
    69
    @tairan2006 #63 join 也可以 select a.*, b.* 来着
    如果有重名不记得是报错还是自动重命名了
    no1xsyzy
    no1xsyzy
    Aug 5, 2020
    70
    @lolizeppelin #31 你 model 不读字段名的吗?
    稍微瞄了眼 SQL92 没看到哪指明 <select list> 的顺序在结果中必须被保持。
    wolong
    wolong
    Aug 5, 2020
    71
    先 select *一把梭,后期出现性能问题了再优化成 select 字段 1, 字段 2
    keenkiller
    keenkiller
    Aug 6, 2020
    72
    @no1xsyzy mysql 会报错,有歧义
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   4933 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 702ms · UTC 07:10 · PVG 15:10 · LAX 23:10 · JFK 02:10
    ♥ Do have faith in what you're doing.