Mysql中select的正确姿势

  大家在开发中,还有很多童鞋在写查询语句的时候,习惯写下面这种不规范sql
  
  select * from table
  
  而不写成下面的这种规范方式
  
  select col1,col2,...,coln from table
  
  我也知道,这些童鞋是图方便,毕竟再敲一堆的列名,嫌麻烦!
  
  你们上班可以问问自己的同事
  
  你:“xx,知道select *和select所有字段的区别么?
  
  同事:"额。。额。。额。。"
  
  留下的只有尴尬的笑容!
  
  我也知道,很多人至今都没有搞懂select *和selct 所有字段的区别
  
  因此,我开一文来说明一下。另外,我选的是自己最熟悉的mysql数据库,此文的结论在oralce,sqlserver上是否成立,博主没做过测试。
  
  正文
  
  (select所有字段)性能高?
  
  网络上流传着一种说法说是
  
  “*” 表示通配所有字段,在SQL的机制里,需要先识别统计所有字段再进行下一步。
  
  明确指定字段的话,会减少上述的操作,所以效率有所提升。
  
  然而,实际上呢?效率是相差不大的!。
  
  取博客
  
  http://flysnowxf.iteye.com/blog/1125032
  
  的测试结果
  
  mysql 5.1.37
  
  表记录数41,547,002,即4000w行
  
  使用远程客户端取1000条数据,统计时间:
  
  SELECT * FROM `dmsp`.`dmsp_dimension_content` LIMIT 0, 1000;
  
  时间2.218s,网络消耗0.547s
  
  SELECT `id`, `appid`, `aop`, `t`, `uid`, `sid`, `pid`, `pname`, `bid`, `bname`, `ptype`, `sm`, `sv`, `bt`, `national`, `area`, `ov` FROM `dmsp`.`dmsp_dimension_content` LIMIT 0, 1000;
  
  取出所有字段,时间2.250s,网络消耗0.578s
  
  可以看出,这二者的时间差几乎可以忽略,另外还有一本书上的内容也可以佐证我的话。
  
  《SQL CookBook》第一章 检索记录中1.1小节(原书第十五页内容如下):
  
  image
  
  此书也说明了,两种方式在性能上几乎是没有差距的。
  
  那为什么还是不推荐select * ?
  
  网络IO问题
  
  很多文章里说什么,会带来额外的内存、磁盘、cpu的开销。对此,我有自己的观点。我觉得这不是主要原因。主要原因是带来了额外的网络开销。
  
  在一个系统中,内存、磁盘、cpu的开销,不过是微妙级。造成系统的延迟的重头戏是网络开销。网络开销可能带来秒级的延迟。当然,如果你的应用程序和数据库是在同一台机器上的,那当我没说这句话!
  
  select *会查询出不需要的、额外的数据,那么这些额外的数据在网络上进行传输,必定会造成性能延迟。假设你的table中,有一个列的类型为binary。此时,你的select *操作,就会十分缓慢,并且会造成额外的网络开销。
  
  索引问题
  
  仔细看下面的两句sql
  
  select col1 from table;
  
  select * from table;
  
  如果col1字段包含索引信息,那么此时,这两句的sql执行时间可能会有几十上百倍的差异。
  
  在col1字段有索引的情况下,mysql是可以不用读data,直接使用index里面的值就返回结果的。但是一旦用了select *,就会有其他列需要读取,这时在读完index以后还需要去读data才会返回结果。这样就造成了额外的性能开销。
  
  ps:我不想在这里扯什么覆盖索引,辅助索引的概念。其实要讲的很专业,扯一堆高大上的名词,我也可以。只是这样徒增读者的理解难度,尽量用通俗的方式来讲。
  
  扩展性问题
  
  有的人会觉得
  
  使用select * ,这样在增加列的时候,不用改sql,方便!
  
  然而实际上,你的sql是不用改了,但是对你的程序代码是有很大的影响的!
  
  身为一名21世纪的优良程序员,我们是不能获取自己需要的东西的!你因为一时高兴,执行了select *,如果增加或删除列,会对你的代码有着极大的影响。
  
  反过来,如果你select 指定列,只获取自己需要的几列,表结构的修改,对你代码的影响就会小很多。相比之下,风险就没有那么大了!
  
  另外就是,对于其他人接手你项目的人来说,看到select 指定列的方式,可读性更强,对于他们来说更好上手!
  
  E:\app\Administrator www.ysyl157.com admin\orcl\dpdump
  
  2、创建用户
  
  create user testdb65 identified by “testdb65”
  
  default tablespace users temporary tablespace temp;
  
  用户授权
  
  grant connect,dba to testdb65;
  
  3、创建表空间
  
  CREATE TABLESPACE HR_DATA01 DATAFILE ‘D:\nhsj\hr_data01.dbf’ SIZE 500M AUTOEXTEND ON NEXT 50M EXTENT MANAGEMENT LOCAL UNIFORM SIZE 256K ; 【创建表空间】
  
  4、导入 bgyhr2是来源库
  
  impdp testdb65/testdb65@orcl schema=www.mcyllpt.com testdb65 dumpfile=TESTDB65.dmp
  
  导出 scott 是要导出的库
  
  expdp lfwtrain/a@orcl schema=当前用户 dumpfile=expdptest.dmp
  
  (18)重导dmp文件
  
  Oracle保存数据时一般以DMP文件的形式进行保存
  
  本博客记录,DMP文件的导入 先打开CMD
  
  sqlplus /nolog
  
  以sysdba连接
  
  conn /as sysdba
  
  这里创建表空间,因为表空间进行存储的话,可以提供系统性能
  
  CREATE TABLESPACE DATA01 DATAFILE 'D:\tablespace\data01.dbf' SIZE 100M AUTOEXTEND ON NEXT 50M EXTENT MANAGEMENT LOCAL UNIFORM SIZE 256K ;
  
  创建用户
  
  CREATE USER job IDENTIFIED BY job DEFAULT TABLESPACE DATA01 TEMPORARY TABLESPACE TEMP QUOTA UNLIMITED ON DATA01
  
  授权
  
  grant connect,dba to job;
  
  复制dmp文件到oracle安装目录里的app\admin\orce\dpdump里,然后用以下代码导入dmp文件,要顺便导入logfile的话,加上logfile=文件名
  
  impdp job/job@orcl schemas=www.dasheng178.com/ job dumpfile=EXPDP160810GZ.dmp
  
  (19)vm_concat函数
  
  函数wm_concat(列名),该函数可以把列值以","号分隔起来,并显示成一行
  
  ps:这个列转行函数vm_comcat(www.yinmaoyule178.com)在oracle10比较稳定,到了oracle11就会出现一些不兼容的情况,oracle12版本就没这个函数了
  
  (20)replace函数
  
  REPLACE(char, search_string [, replacement_string ] )
  
  char : 等待替换的字符串
  
  search_string : 搜索需要替换的字符串
  
  replacement_string : 替换字符串
  
  如果replacement_string缺省或者为null,那么所有char中出现的search_string 都将被移除
  
  如果search_string为null,那么结果就是char
  
  例子:过滤某个字段的换行符
  
  select replace(a, chr(10)) from tableA
  
  1
  
  (21) instr函数
  
  格式一:instr(www.ylouyi3.com string1, string2 ) / instr(源字符串, 目标字符串)
  
  格式二:instr( string1, string2 [, start_position [, nth_appearance ] ] ) / instr(源字符串, 目标字符串, 起始位置, 匹配序号)
  
  解析:string2 的值要在string1中查找,是从start_position给出的数值(即:位置)开始在string1检索,检索第nth_appearance(几)次出现string2。
  
  例子:查询某个数据字段是否包含换行符
  
  select * from tableA where instr(a,chr(10))>0

猜你喜欢

转载自blog.csdn.net/li123128/article/details/83713195