加速SQL查询效能的七大秘诀

  任何平台的SQL开发者都有自身的困惑,似乎他们一直纠缠在DO WHILE循环里,这个循环让他们不断地重复同样的错误。这是因为数据库的发展依然不够成熟。当然,供应商们也在不断进步,但是他们还是需要处理更严重的问题。并发性,资源管理,空间管理和速度依然制约着SQL开发者对开发平台的选择。

  部分问题是因为没有诀窍可以实现解决这些问题,也没有任何实践表明已经解决了这些问题。但是,至少我可以告诉你这里有一个例外。通常,开发者会找到自己喜欢的方法,尽管这些方法无法实现性能架构和并发性,但是开发者也不会再自找麻烦地去寻找别的方式了。或许这是缺少教育的后果,或许是因为开发者太接近这些进程了,所以就没办法认清他们产生的错误。可能在本地测试系统上这些查询代码可以运行良好,但是在运行系统上就会产生极大的错误。

  我并不期望SQL开发者能成为管理员,但是在写代码的时候,他们必须重视生产问题。如果在开发初期他们就不做这些工作,那么,DBAs将强制他们回过头来考虑这个问题,以此同时,使户也会受到影响。

  我们之所以说调整数据库是一件艺术性和科学性结合的事情,是因为在应用上来看有很多必须遵守的规则。你在一个系统里解决的问题,在另一个系统里依然会出现,反之亦然。在调整数据库方面没有万能的答案,但是你依然不能放弃。

  下面我将总结出在SQL编程中容易被忽略的一些注意要点,哪些是可以做的,哪些是不可以做的。这些要点将帮你更加深入地理解DBAs,也可以增强你从面向生产的角度思考进程。

  1.不要用UPDATE代替CASE

  尽管这个问题经常被忽略,但是却是一个很普遍的问题。很多开发者都会忽略这个问题,因为使用UPDATE看起来是一个具有逻辑性的自然流。

  在这种情况下,例如:你插入一个临时表格,在存在另一个值的时候,让它显示某个值。你要从客户表中按顺序列出超过10万美金的人,以便把他们设置为“首选”。这时,你就要把数据插入表格中,运行UPDATEA命令来设置CustomerRank列,来顺序定义那些超过10万美金的人。问题是,UPDATE命令已经被记录了,这就意味着针对每一个表写入你都要进行两次操作。当然,针对这个过程可以使用SQL查询语言本身的CASE语句。它将测试每一行是否符合总体条件,并在写入表格前,给它一个“首选”的标签。这种性能的提高是惊人的。

  2.不要盲目使用代码

  这个也是很普遍的。这很容易复制别人的代码,因为你知道它这段代码可以查询到你需要的资料。问题是,很多时候复制别人的代码会让你得到很多你不需要的额外资料。但是很少有开发者有功夫去挑选这些数据。所以他们也只是通过这些代码得到了需要数据的父集。这样的代码通常是以外部链接的方式或者是在WHERE语句中出现。所以说如果你有针对性地修改代码,SQL的性能就会得到大大的提升。

  3.只查询对你游泳的列

  这个问题和第二个问题类似,但是,是针对列来讲的。用SELECT * 查询,而不是分别对每列查询在代码实现方面也简单地多。但是这时,问题再一次出现,你再次得到了比你需要的数据多得多的数据。我已经无数次地看到这种现象发生了。开发者用SELECT * 语句查询一个120列、几百万行的表以后最后只得到了3到5行的有用数据。在这一点上,你不是仅仅查询了比你所需要的数据多的数据,你还从别的进程中抢夺了资源,降低了整体速度。

  4.不要做两次查询

  还有一个常见的现象是:写一个从拥有无数行的表里取数据的存储进程。开发者需要查询到符合这样以下条件的用户:住在加利福尼亚州,收入超过$40,000。这时,他把住在加利福尼亚州的客户查出来放到一张零时表中,然后把收入在$40,000以上的客户查出来放到另一张零时表中。最后,他合并这两个表得到最终的查询结果。然后,通过更小的数据集,来加强后续步骤。

  你在开玩笑吧?这个查询应该是一个单一的查询,可是,你却对一个如此大型的表进行了两次查询。不要再做这样的傻事了:对大型表格说,尽可能地只进行一次查询。这时,你会发现你的程序执行起来效率更高了。

  稍微不同的地方是,当我们需要通过几个步骤查询一个大型表的子集时,它将导致对大型表的多次查询。一定要通过查询子集避免这种事情的发生。

  5.确定使用临时表的时机。

  这是一个比较难以处理的问题,但是你可以从这里得到很多好处。很多情况下,都是可以使用临时表的,比如:在避免两次从一个大型表格里查询时。在连接两个表格的时候,你也可以使用临时表来大大降低处理程序所占用的内存。如果你必须把一个表合并到一个大型表格中,你可以通过先从大型表中检索出你所需要的数据合并到临时表中,然后用把这些数据合并的方法来优化命令。如果在进程中,你必须对同一个表进行同样的合并的时候,临时表是一个非常有用的方式。

  6.必须预存数据。

  这是我比较喜欢的一个话题,因为这是一个比较容易被忽略的老方法。如果你有一个报告或者一个进程,它们需要向一个大型表里做类型的合并,这时,如果你能通过提前合并表格或者是插入表格的方法来预存数据,这将对你的操作大大有益。

  一般情况下,你是不能使用这个技巧的。但是,如果你可以,你会发现这将是一个非常完美的节约服务器资源的方法。

  注意到这样的问题,一般开发者通过关注查询本身而避开这样的合并问题,创建一个只可见的合并,以致于不能一而再,再而三地定义它们的合并环境。通过预存数据,你只需执行一次合并,同时别人也避免了大型的合并。我非常喜欢用这种方法,大多数情况下,有很多流行表总是执行合并,所以没有任何理由说不能预存数据。

  7,分批地删除和更新。

  还有一个常被忽略的简单技巧。如果你的操作错误,从一个大型表里删除和更新大量的数据将是一个噩梦。问题是这两个命令执行起来就像是一个命令,如果你需要放弃他们,或者如果你在工作的时候系统发生了什么事情,系统就必须从头开始所有命令的执行。这会花费很多时间。这些操作也会妨碍别的命令的执行,甚至会成为整个系统的瓶颈。

  解决这个问题的办法是,小批量地删除和更新数据。可以通过两种方式来解决这个问题:一,如果命令的执行因为任何原因被终止,那就必须有一小部分行从头开始执行,所以数据库恢复得将会快得多。二,当更少的数据被存在了硬盘上时,别的命令也可以做一些工作,所以并发性就被大大地优化了。

  按照这个指示,很多开发者企图在一天之内把这些删除和更新操作完成。但是,这并不是总是正确的,特别是当你在存档的时候。只要你需要,你可以尽可能地扩展这些炒作,而且这些小批量的数据也可以帮助你完成这些。如果你可以花费更多的时间来做更多的操作,那么就花费一些多余的时间吧,同时不要让你的系统停下来。

  当你写代码来优化你的SQL性能的时候,在任何你可以遵守这些事项的时候,就去遵守它们。但是,请分别评价这些解决方法来看看哪种方法是最有效的,可以说没有一个万能的或者是固定的方法来解决这些问题。你将会发现很多窍门都是和ikyi提高并发性,并可以让整体运行通畅的。同时,你也会注意到这些物理实现会从这个供应商传递到下一个供应商,这些概念和问题将会存在每一个SQL平台上。

你可能感兴趣的:(sql)