
事故
原则上,我是赞成在一般情形下使用select *的。这里所说的一般情形是指:由于对象关系映射(ORM)的关系,在这种情况下基本上肯定是要获取这个实体的全部数据的。并且,通过ORM产生select *这种操作的语义非常清晰,就是要查询出这个实体。在这种时候,把列名明确地写出来只会徒增麻烦。例如增加列的时候,要在类(class)或者结构体(struct)里多写一个字段,之后还得额外去修改所有的SQL(不过确实存在某些ORM能够自动生成将所有列名都明确写出的SQL)。要是删除列的话,明确写出列名的select语句是有引发线上
事故风险的。有时候列名和字段名是存在差异的(比如类里有个字段叫rank,表示某种排序,但rank是
MySQL的关键字,所以列名就得改成xxx_rank),通过ORM注解等方式就能够一次性解决这个问题。要是再明确地写列名,就很容易写错,从而造成不必要的开发时间浪费。考虑到blob、text列的因素是因为这种列会显著导致查询速度变慢。有时候为了优化,我们甚至会把这种列单独提取出来建立一张表,编写独立的查询代码。但是如果没有这种情况,只是一些常规的bigint、int、varchar类型的列,而且列数没有多到离谱的程度,那么性能损耗是不明显的。但这并不是说就可以任由程序员随意编写了。比如我们每次上线之后都要评估关键接口的性能指标,如果有明显的性能下降就能够迅速发现并找出原因。有很多人提到索引覆盖,这个道理也没错。大致估算一下,一般来说在100个查询里,能够适合用索引覆盖来优化的查询不到5个。所以从实际操作来看,我认为这不是一个普遍存在的问题。例如对于一张a_b_ref表,根据a查询b或者反过来根据b查询a。你可能以为有索引覆盖了对吧。但是第二天需求就说查询出来的ref要按照ref的创建时间(created_at,肯定不在a、b这个索引里)进行排序……所以,我只能衷心祝愿那些对索引覆盖极为敏感的
同学面试顺利。所以,我的观点和其他几位高赞回答者都不一样:综合性价比来考虑,在性能下降情况出现之前,引入明确写出列名的select语句可能成本更高。但是你得有办法知道什么时候性能在下降!随着业务的不断增加,列数也会持续增多,一般都会在某个阶段将整个数据整体打包成pb、thrift或者avro格式进行存储。或者把整个数据都迁移到类似T
AIr之类的地方。原本使用数据库索引查询的部分会保留(只会保留少数几列),或者直接引入ES。这种优化可不仅仅是select语句写法这么简单的问题了。