Document

查询反模式 - 隐式的列

一、减少输入

  程序员都喜欢使用通配符,如:

    SELECT * FROM Person

  又或者省略字段名:

  INSERT INTO Person VALUES('10','张飞'...)

二、捷径会让你迷失方向

  对于以上代码,如果你仅仅是在开发过程中用于查看一下数据库信息,又或者你只是写个小程序自己玩玩,这是没有什么问题的。

  但是如果一旦你习惯于这样编写正式生产环境中的代码,那问题就随之而来了。

  1、破坏代码重构

  如果数据库更改了,比如增加了一列:

  ALTER TABLE Person Add Age int

  这下糟糕了,你程序中所有的

  INSERT INTO Person VALUES(...)

  语句都会报错。

  早使用这种隐式模式执行INSERT时,输入必须严格按照定义表时的那些列的顺序,如果列变了,这条语句就会抛出一个错误,甚至有可能就会抛出一个错误,甚至有可能把数据写到错误的列里面去。

  假设原本是使用隐式模式查询:

  SELECT * FROM Person

  但是加入删掉了中间的一个列:

    ALTER TABLE Person DROP COLUMN Age

  那么加入是使用DataTable的方式装载数据库内容,那么row[10]可能就已经不是第十个。在重命名、添加、删除列的时候,程序代码并不能适应查询结果的改变。如果使用了通配符,就无法预测这个查询会返回多少行。

  2、隐藏的开销

  在查询中使用通配符可能会影响性能和扩展性。一次性查询所获取的列越多,客户端程序和数据库之间的网络传输的字节也越多。

  生产环境中的程序可能会有很多并发的查询请求。它们都共享同一个网络带宽。太多客户端同时查询返回上千条记录可能会造成阻塞。

  3、合理使用反模式

  在你只是为了快速地写几个脚本对一个解决方案进行测试,或者写临时SQL查询对当前数据进行查看时,使用通配符是合情合理的。只执行一两次的查询对可维护性没有任何要求。

  当然,输入一张很多列的表的所有列名是很耗时的,对某些人来说,开发效率可能比程序运行效率更加重要。例如,当你开发的是较少用户量的小公司内部访问程序,这时候返回数据所使用的带宽比查询语句本身要多得多。这时候没必要纠结这些问题。

三、解决方案-明确列出列名

  1、预防错误

  每次查询都列出所有你需要用到的列,而不是使用通配符或者隐式列的列表。

  SELECT Id,Name... FROM Person
  INSERT INTO Person (Id,Name,Age...) VALUES(1,'张飞',22...)

  这样做的好处如下:

  •   如果这张表的某一列的位置被移动过,他不会对返回结果中这一列的位置造成影响。
  •   如果这张表中新加入一列,它是不会出现在查询结果中的。
  •   如果从这张表中删除一列,你的查询会得到一个错误,但是直接就能够找到问题所在,这是符合尽早出错原则的。

  2、减少资源占用

  如果必须关心软件的可扩展性和程序的吞吐量,你应该检查一下网络传输过程中可能造成的浪费。一旦在SQL中禁用通配符,那么就很自然地去除那些不需要的列,提高了带宽和内存的使用效率。

posted @ 2017-07-13 14:37  从未被超越  阅读(185)  评论(0编辑  收藏  举报