3

我试图找出以下是否是用于减少应用程序延迟的有据可查的模式(或反模式)。我已经尝试过这种技术,从表面上看,这似乎为我节省了大约 20% 的延迟。我想知道是否有任何我应该注意的副作用

语境:

你有一个方法/函数/过程,它对数据库进行多次 SELECT 调用,你需要优化它。

假设您的方法流程是:

  getDBConnection()  
  execute("Select a,b from tableA");  
  bind a with varA 
  bind b with varB  
  ---SOME Business Logic-----  
  execute("Select c,d from tableB");  
  bind c with varC  
  bind d with varD   
  ---SOME more Business Logic-----  
  execute("Select e,f from tableC");  
  bind e with varE  
  bind f with varF  
  ---SOME more Business Logic-----  
  releaseConnection()

解决方案:使用 Union ALL 对数据库进行一次调用

 getDBConnection()
 execute("Select a,b,'sqlA' from tableA"+  
 " UNION ALL "+  
 " Select c,d,'sqlB' from tableB"+  
 " UNION ALL "+
 "Select e,f,'sqlC' from tableC");  
 bind a,b where records have "sqlA"   
 bind c,d where records have "sqlB"
 bind e,f where records have "sqlC"  
 releaseConnection()  
 --------Do all Business Logic here-----
4

2 回答 2

6

使用union限制了查询的“形状”。它们基本上必须以相同的顺序返回相同数量和(兼容)类型的列。

更好的方法是在单个命令中使用多个查询,然后处理多个结果集:

execute("Select a,b from tableA;"+
  "Select c,d from tableB;"+
  "Select e,f from tableC");

或者可能创建一个运行这些查询的专用存储过程。

除此之外,这种优化技术可以将不相关的操作集中在一起,这将限制以后单个操作的可重用性。您可能需要考虑一种更好地分离这些操作并使用某种类型的设计QueryManager来首先收集它们,然后将它们一起运行。

于 2011-07-07T18:44:23.980 回答
1

把所有东西放在一起可能会掩盖真正的问题:你知道延迟来自哪里吗?

如果多次调用这些查询,您可能会在编译阶段花费大量时间。如果表在应用程序的生命周期内没有发生太大变化,使用准备好的语句可能会有所帮助:

conn = connect_to_db()
pstmt = conn.prepare('select ...')
...
pstmt.bind(parameters) // if necessary
pstmt.execute()

如果延迟不是来自编译,它可能是执行 - 您给出的查询是简单的选择,但任何更复杂的可能需要检查解释计划。

如果您的 dbms 和表的结构允许,一些重组也可能有助于减少需要完成的查询量:您可以将 select 语句与 join 而不是 union 结合起来吗?您可以将表与分区合并吗?

这都是一堆一般的想法。要回答您的实际问题,我以前没有见过这种方法,但我不会让恶名成为唯一的决定因素。正如之前的海报指出的那样,您可能会牺牲代码的可重用性。最后,随着表数量的增长,这种方法不会很好地扩展:您仍然需要在应用程序代码中查找哪些行具有“sqlA”、哪些行具有“sqlB”等。

于 2011-07-08T15:31:29.950 回答