我调查了很多地方,听到了很多可疑的说法,从 PreparedStatement 应该比 Statement 更受欢迎,即使只是为了性能优势;一路声称 PreparedStatement 应该专门用于批处理语句,而不是其他。
但是,我关注的(主要是在线的)讨论似乎存在盲点。让我展示一个具体的场景。
我们有一个带有数据库连接池的 EDA 设计的应用程序。事件来了,有的需要坚持,有的不需要。有些是人为生成的(例如,每 X 分钟更新/重置一些内容)。 一些事件按顺序发生和处理,但其他类型的事件(也需要持久性)可以(并且将会)并发处理。
除了那些人为生成的事件之外,没有关于需要持久化的事件如何到达的结构。
此应用程序是很久以前(大约 2005 年)设计的,支持多个 DBMS。典型的事件处理程序(需要持久化的地方):
如果事件需要批处理,语句准备一次并使用addBatch/executeBatch 方法。这是一个明显的性能优势,这些情况与此问题无关。
最近,我收到了一个意见,即准备(解析)一条语句、执行一次并关闭的整个想法本质上是对 PreparedStatement 的滥用,提供了零性能优势,无论是使用服务器还是客户端准备语句,典型的 DBMS(Oracle、DB2、MSSQL、MySQL、Derby 等)甚至不会将此类语句提升到准备语句缓存(或至少是它们的默认 JDBC 驱动程序/数据源)不会)。
此外,我不得不在 MySQL 的开发环境中测试某些场景,Connector/J usage analyzer 似乎同意这个想法。对于所有非批处理的准备好的语句,调用 close() 打印:
PreparedStatement 已创建,但使用次数不超过 1 次。一次准备语句,多次重复使用它们效率更高
由于前面概述的应用程序设计选择,拥有一个 PreparedStatement 实例缓存来保存连接池中每个连接的任何事件使用的每个 SQL 语句听起来是一个糟糕的选择。
有人可以进一步详细说明吗? 逻辑“准备-执行(一次)-关闭”是否存在缺陷并且基本上不鼓励?
附言为 Connector/J 明确指定 useUsageAdvisor=true 和 cachePrepStmts=true 并使用 useServerPrepStmts=true 或 useServerPrepStmts=false 在 每个 非批处理 SQL 语句的 PreparedStatement 实例上调用 close() 时,仍然会导致效率警告。
最佳答案
Is the logic prepare-execute [once]-close flawed and essentially discouraged?
我不认为这是一个问题,本身。给定的 SQL 语句需要在某个时刻进行“准备”,无论是显式(使用 PreparedStatement)还是“即时”(使用 Statement)。如果我们使用 PreparedStatement 而不是 Statement 来处理只会执行一次的内容,可能会产生更多的开销,但所涉及的开销不太可能很大,特别是如果您引用的语句是正确的:
typical DBMSes (Oracle, DB2, MSSQL, MySQL, Derby, etc.) will not even promote such a statement to prepared statement cache (or at least, their default JDBC driver/datasource will not).
不鼓励使用这样的模式:
for (int thing : thingList) {
PreparedStatement ps = conn.prepareStatement(" {some constant SQL statement} ");
ps.setInt(1, thing);
ps.executeUpdate();
ps.close();
}
因为 PreparedStatement 只被使用一次,而且同一个 SQL 语句被一遍又一遍地准备。 (尽管如果确实缓存了 SQL 语句及其执行计划,即使那样也不是什么大问题。)更好的方法是
PreparedStatement ps = conn.prepareStatement(" {some constant SQL statement} ");
for (int thing : thingList) {
ps.setInt(1, thing);
ps.executeUpdate();
}
ps.close();
...甚至更好,“尝试使用资源”...
try (PreparedStatement ps = conn.prepareStatement(" {some constant SQL statement} ")) {
for (int thing : thingList) {
ps.setInt(1, thing);
ps.executeUpdate();
}
}
请注意,即使不使用批处理也是如此。 SQL语句仍然只准备一次,多次使用。
关于java - 单次执行后关闭 PreparedStatement——这是设计缺陷吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33065643/
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试
这个问题在这里已经有了答案:Arraysmisbehaving(1个回答)关闭6年前。是否应该这样,即我误解了,还是错误?a=Array.new(3,Array.new(3))a[1].fill('g')=>[["g","g","g"],["g","g","g"],["g","g","g"]]它不应该导致:=>[[nil,nil,nil],["g","g","g"],[nil,nil,nil]]
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
下面的代码在我第一次运行它时就可以正常工作:require'rubygems'require'spreadsheet'book=Spreadsheet.open'/Users/me/myruby/Mywks.xls'sheet=book.worksheet0row=sheet.row(1)putsrow[1]book.write'/Users/me/myruby/Mywks.xls'当我再次运行它时,我会收到更多消息,例如:/Library/Ruby/Gems/1.8/gems/spreadsheet-0.6.5.9/lib/spreadsheet/excel/reader.rb:11
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我