关于SQL中SELECT *(星号)的危害论
听闻有许多人是禁止开发人员在SQL中使用SELECT *的,这里翻译一下StackOverflow的一篇提问,个人认为相当客观
【SELECT *】危害主要有以下几点:
- 给数据消费者传数据的低效。当你SELECT *后常常你会从数据库查询出比你应用的功能实际需要过多的列,这还可能导致多余数据从数据到服务端到客户端,从而导致机器负担的增加,同样地网络传输也会增加负担。特别当数据表增加了新列,但是功能实现那根本又不需要。
- 索引问题。想象一下这样一个场景:你需要调一个Query调到一定的高性能。如果你用了SELECT *然后返回全部列超过了你需要的列,服务端经常需要为接收你的数据而消耗代价更多的函数而本来是不用的。举个例子,你不可能简简单单创建一个覆盖你SELECT出来全部列的索引,即使你这样做了(包含全部列,想想都可怕),下一个挖坑人又在数据表中增加了新的列就导致你原本已覆盖的索引无法优化了,然后你会惊奇地发现你的Query性能噗噗噗地下降,又没有明显的原因。
- 绑定问题。当你SELECT *之后,有可能查询到来自两张表但是名称一样的列。这样可能会引起数据绑定端或者功能点崩溃,想想返回来有两列数据都是ID,谁TM知道用哪一列?SELECT *还可能搅乱视图(部分数据库、版本)——当底层数据表结构改变,视图又没有新建,视图的数据可能会返回无意义的数据(名称乱不好维护?)。最惨的,你能折腾好以你命名的列,但新来的挖坑人要加入列的时候就不知道他应该如何命名列名才不会与你已经埋好的列名冲突了。
但并不是说【SELECT *】只有坏处,以下用例就可以宽泛地使用:
- 临时查询。当调试东西,特别是某一表自己不熟悉的时,SELECT *就显得很友好了。自己就不用先研究一番这表有啥表明了。这样表的列名越长SELECT *加分就越高。
- 当*表示一行。在下面的用例中SELECT *没啥问题的——之前也有谣传这样写是性能杀手,也许这传说几年前还有点说服力,但是现在不是:
SELECT COUNT(*) FROM table;
在此用例中“*”表示“数一下行数”,如果你用列名替代这表示要数一下列对应值不为NULL的行数。对我来说,COUNT(*)才是本质意义的数行数,这样你也避开了擦边案例(例如聚合搜索中应被消除的NULL值)【译者觉得还是COUNT(Id)或者COUNT(主键)靠谱,这里只是说明数行数的情况,即SELECT * 代表一行时使用没啥毛病】
以下类型的Query也是一样的:SELECT a.ID FROM TableA a
WHERE EXISTS (
SELECT *
FROM TableB b
WHERE b.ID = a.B_ID);在任何合格的数据库中,“*”就是表示“一行”,不管你在子查询中放了啥。一些人用在SELECT中用ID或者数字1,在我看来在这些约定相当的扯淡。你的意思是要“数行数”,“*”就是用来干这个的。做这些查询优化的知道这个的都是智者。(实际上,我只知道SQL Server和Oracle就是这样的)
关于SQL中SELECT *(星号)的危害论的更多相关文章
- SQL中SELECT INTO和INSERT INTO SELECT语句介绍
表复制是经常要用到的操作,下面就将为您介绍SQL中SELECT INTO和INSERT INTO SELECT语句,供您参考. Insert是T-sql中常用语句,Insert INTO table( ...
- PL/SQL中SELECT总结
一.SELECT 语句的各个关键词的顺序及作用简解(这个我简略点写~) 1.SELECT 2.FROM 3.WHERE 4.GROUP BY ---对结果集进行分组,通常与聚合函数一起使用 5.H ...
- SQL 中 SELECT 语句的执行顺序
好像自已在书写 SQL 语句时由于不清楚各个关键字的执行顺序, 往往组织的 SQL 语句缺少很好的逻辑, 凭感觉 "拼凑" ( 不好意思, 如果您的 SQL 语句也经常 " ...
- 在sql中select的执行顺序
<select{[distinct |all] columns |*}> [into table_name] <from {tables |views | other select} ...
- 【SQL】SQL 中Select语句完整的执行顺序
SQL Select语句完整的执行顺序: 1.from子句组装来自不同数据源的数据: 2.where子句基于指定的条件对记录行进行筛选: 3.group by子句将数据划分为多个分组: 4.使用聚集函 ...
- sql中select into和insert into的区别
select into主要是作用于没有新建表,在复制数据的时候新建 insert into主要作用于已经新建了一个表,直接把要复制的数据复制到新建好的表中
- \G,sql中select 如果太长,可以在后面放\G,竖行显示~~~~
1.使用\G按行垂直显示结果 如果一行很长,需要这行显示的话,看起结果来就非常的难受. 在SQL语句或者命令后使用\G而不是分号结尾,可以将每一行的值垂直输出. mysql> select * ...
- SQL中select与set的区别-转载
下表列出 SET 与 SELECT 的区别 SELECT SET 同时对多个变量同时赋值时 支持 不支持 表达式返回多个值时 将返回的最后一个值赋给变量 出错 表达式未返回值时 变量保持原值 变量 ...
- sql中select语句的逻辑执行顺序
下面是SELECT语句的逻辑执行顺序: FROMONJOINWHEREGROUP BYWITH CUBE or WITH ROLLUPHAVINGSELECTDISTINCTORDER BYTOP M ...
随机推荐
- 闲话Dicom
最近在准备一场有关DICOM应用的讲座,整理了一下思路.想了几个问题,发现挺有意思的,想与大家共同分享.接触过DICOM,应该了解普通DICOM 文件包含的四级属性,病人,检查,序列,影像.每一级别需 ...
- Java编程思想之八多态
在面向对象的程序设计语言中,多态是继数据和继承之后的第三张基本特征 多态不但能够改善代码组织结构和可读性,还能够创建可扩展的程序--即无论在项目最初创建时还是在需要添加新功能时都可以"生长& ...
- SpringCloud之application.properties和bootstrap.properties区别
Spring是有上下文一说的,也叫Application Context,Application Context又是有父子关系的,所以必须要理解ApplicationContext是什么.Spring ...
- Behavior Trees for Path Planning (Autonomous Driving)
Behavior Trees for Path Planning (Autonomous Driving) 2019-11-13 08:16:52 Path planning in self-driv ...
- Python2.7 删除前N天日志文件
Python2.7 删除前N天日志文件 import os import sys import time day_n = 7 path=os.getcwd().replace("\\&quo ...
- linux查看占用内存前10的命令
- 爬虫中Selenium和PhantomJS
Selenium Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键精灵,可以按指定的命令自动操作,不同是Selenium 可以直接运行在浏览器上, ...
- mac软件安装 for Mac
Office 2019 for Mac 16.31(191110)官方原版安装包&激活 赠送Office 2016 16.16.16(191111) --------- https://www ...
- 【APM】Pinpoint 使用教程(二)
本例介绍Pinpoint使用教程 Pinpoint安装部署参考:[APM]Pinpoint 安装部署(一) 查看应用调用关系拓扑图 进入pintpoint->选择应用-〉选择查看的时间周期,即可 ...
- k8s记录-Dockerfile详解
Dockerfile命令详解 下面我们来分别介绍下上面使用到的命令: FROM 格式:FROM 或FROM :. 解释:FROM必须是Dockerfile里的第一条指令(注视除外),后面跟有效的镜像名 ...