这是一个有据可查的模式吗?
我试图找出以下内容是否是一个有据可查的模式(或反模式),用于减少应用程序延迟。我已经尝试过这种技术,从表面上看,这似乎为我节省了大约 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-----
I am trying to find if the below is a well documented pattern (or anti-pattern for that matter) for reducing application latency. I have tried this technique and on face this looks to be saving me some 20% in latency. I would like to know if there are any side affects that I should be aware of
Context:
You have got a method/function/procedure which makes multiple SELECT calls to database and you need to optimize it.
lets say the flow of your method is :
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()
Solution :
Use Union ALL to make a single call to Database
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-----
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
union
的使用限制了查询的“形状”。它们基本上都必须以相同的顺序返回相同数量和(兼容)类型的列。更好的方法是在单个命令中使用多个查询,然后处理多个结果集:
或者创建一个运行这些查询的专用存储过程。
除此之外,这种优化技术可以将不相关的操作集中在一起,这将限制以后各个操作的可重用性。您可能需要考虑一种设计,可以更好地分离这些操作,并使用某种
QueryManager
首先收集它们,然后将它们一起运行。The use of
union
limits the "shape" of your queries. They basically have to all return the same number and (compatible) types of columns, in the same order.A better approach would be to use multiple queries in a single command and then deal with multiple result sets:
Or maybe create a dedicated stored procedure that runs these queries.
Apart from this, this optimization technique can lump together unrelated operations, which will limit the reusability of individual operations later on. You might want to consider a design that better separates these operations and uses some kind of
QueryManager
to first collect them and later run them all together.将所有内容放在一起可能会掩盖真正的问题:您知道延迟来自哪里吗?
如果多次调用这些查询,您可能会在编译阶段花费大量时间。如果表在应用程序的生命周期内没有太大变化,那么使用准备好的语句可能会有所帮助:
如果延迟不是由编译引起的,则可能是执行造成的 - 您给出的查询是简单的选择,但任何更复杂的查询都可能需要检查解释计划。
如果您的 dbms 和表结构允许,一些重组也可能有助于减少需要完成的查询量:您可以将 select 语句与 join 而不是 union 结合起来吗?可以通过分区合并表吗?
这就是一堆一般想法。为了回答你的实际问题,我以前没有见过这种方法,但我不会让恶名成为唯一的决定因素。正如前面的海报所指出的,您可能会牺牲代码的可重用性。最后,随着表数量的增长,这种方法的扩展性不会很好:您仍然需要在应用程序代码中查找哪些行具有“sqlA”、哪些行具有“sqlB”等。
Pushing everything together may mask the real problem: Do you know where the latency is coming from?
If these queries are called many times you may be spending a lot of time on the compilation phase. Using prepared statements might help if the tables don't change too significantly during your application's lifetime:
If the latency isn't from compilation it may be execution - the queries you gave are simple selects, but anything more complex might warrant an examination of explain plans.
If your dbms and your tables' structure allow it, some restructuring might also help cut back on how much querying needs to be done: Can you combine the select statements with a join instead of a union? Can you merge the tables with partitioning?
That's all a bunch of general ideas. To answer your actual question, I haven't seen that approach used before but I wouldn't let notoriety be the only deciding factor. As the previous poster pointed out you might sacrifice code reusability. Finally, as the number of tables grows this approach won't scale very well: you'll still have to look up which rows have "sqlA", have "sqlB", etc. in the application code.