我试图找出以下是一个记录良好的模式(或反模式),以减少应用程序延迟。我已经尝试过这种技术,但从表面上看这似乎可以节省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-----
答案 0 :(得分:6)
使用union
会限制查询的“形状”。它们基本上必须以相同的顺序返回相同数量和(兼容)类型的列。
更好的方法是在单个命令中使用多个查询,然后处理多个结果集:
execute("Select a,b from tableA;"+
"Select c,d from tableB;"+
"Select e,f from tableC");
或者可以创建一个运行这些查询的专用存储过程。
除此之外,这种优化技术可以将不相关的操作混为一谈,这将限制以后各个操作的可重用性。您可能需要考虑更好地分离这些操作的设计,并使用某种QueryManager
来首先收集它们,然后将它们全部一起运行。
答案 1 :(得分:1)
将所有内容推到一起可能会掩盖真正的问题:您知道延迟的来源吗?
如果多次调用这些查询,您可能会在编译阶段花费大量时间。如果表在应用程序的生命周期内没有太大的变化,那么使用预准备语句可能会有所帮助:
conn = connect_to_db()
pstmt = conn.prepare('select ...')
...
pstmt.bind(parameters) // if necessary
pstmt.execute()
如果延迟不是来自编译,则可能是执行 - 您提供的查询是简单的选择,但任何更复杂的查询都可能需要检查解释计划。
如果你的dbms和你的表的结构允许,那么一些重组也可能有助于减少需要完成多少查询:你能否将select语句与连接而不是联合组合?你可以将表与分区合并吗?
这就是一堆一般性的想法。为了回答你的实际问题,我没有看到以前使用过的方法,但我不会让恶名成为唯一的决定因素。正如之前的海报所指出的那样,您可能会牺牲代码的可重用性。最后,随着表的数量的增加,这种方法的扩展性不会很好:你仍然需要在应用程序代码中查找哪些行有“sqlA”,“sqlB”等。