草庐IT

java - SELECT 上的 JDBC 连接器太慢

coder 2023-10-24 原文

这在网上不是很少见的问题,但我用 MySQL 服务器做了一些优化工作来解决这个问题,但没有得到结果。所以一开始我使用maven的包mysql:mysql-connector-java:6.0.6。 我试着运行这段代码:

try {
            mysqlConnection = DriverManager.getConnection(DatabaseUtils.mysqlUrl, DatabaseUtils.mysqlUser, DatabaseUtils.mysqlPassword);
            PreparedStatement valuesStatement = "SELECT * FROM `test` ORDER BY `id`"
            ResultSet cursor = valuesStatement.executeQuery();
            double value = 0;
            if (cursor.next())
                value = cursor.getDouble("value");
        } catch (SQLException sqlEx) {
            sqlEx.printStackTrace();
        } finally {
            cursor.close();
            pricesStatement.close();
        }

我的表里有很多记录。它大约是百万,但每天都会添加大约一千条记录。所以当这个简单的例子执行了 30 秒时,我感到非常惊讶。我用谷歌搜索我的问题,我只找到“使用池”、“调整 mysql 服务器”、“尝试解释选择”。但我注意到执行时间与行数有关。所以我查看了驱动程序的代码,发现:

TextResultsetReader::read():

        while(true) {
            if(row == null) {
                rows = new ResultsetRowsStatic(rowList, cdef);
                break;
            }

            if(maxRows == -1 || rowList.size() < maxRows) {
                rowList.add(row);
            }

            row = (ResultsetRow)this.protocol.read(ResultsetRow.class, trf);
        }

这意味着即使我只想获取一个行,驱动程序也会获取所有查询的行并让我先获取它。手册建议使用“setFetchSize”来仅获取 n 条记录。但它不起作用。无论如何,驱动程序代码都在获取所有数据。然后我发现有两个记录集:ResultRowsStatic 和ResultSetStreaming。第二个似乎只在我需要查询时才获取数据。如何使用 ResultRowsStreaming?我发现它只进入代码。参数“fetchSize”必须等于 -2147483648。我确实尝试过并且有效! “executeQuery()”的执行时间现在大约为 0.0007 秒。这对我来说非常快。但是等等.. 我的脚本无论如何需要 30 秒。为什么?我在执行查询后调试了代码。之后只有两个“关闭”方法。什么会出错?没错,“cursor.close()”占用了剩下的时间。我再次查看了库代码并找到了 ResultsetRowsStreaming::close():

boolean hadMore = false;
int howMuchMore = 0;
synchronized(mutex) {
    while(this.next() != null) {
        hadMore = true;
        ++howMuchMore;
        if(howMuchMore % 100 == 0) {
            Thread.yield();
        }
    }

    if(conn != null) {
        if(!((Boolean)this.protocol.getPropertySet().getBooleanReadableProperty("clobberStreamingResults").getValue()).booleanValue() && ((Integer)this.protocol.getPropertySet().getIntegerReadableProperty("netTimeoutForStreamingResults").getValue()).intValue() > 0) {
            int oldValue = this.protocol.getServerSession().getServerVariable("net_write_timeout", 60);
            this.protocol.clearInputStream();

            try {
                this.protocol.sqlQueryDirect((StatementImpl)null, "SET net_write_timeout=" + oldValue, (String)this.protocol.getPropertySet().getStringReadableProperty("characterEncoding").getValue(), (PacketPayload)null, -1, false, (String)null, (ColumnDefinition)null, (GetProfilerEventHandlerInstanceFunction)null, this.resultSetFactory);
            } catch (Exception var9) {
                throw ExceptionFactory.createException(var9.getMessage(), var9, this.exceptionInterceptor);
            }
        }

        if(((Boolean)this.protocol.getPropertySet().getBooleanReadableProperty("useUsageAdvisor").getValue()).booleanValue() && hadMore) {
            ProfilerEventHandler eventSink = ProfilerEventHandlerFactory.getInstance(conn.getSession());
            eventSink.consumeEvent(new ProfilerEventImpl(0, "", this.owner.getCurrentCatalog(), this.owner.getConnectionId(), this.owner.getOwningStatementId(), -1, System.currentTimeMillis(), 0L, Constants.MILLIS_I18N, (String)null, (String)null, Messages.getString("RowDataDynamic.2") + howMuchMore + Messages.getString("RowDataDynamic.3") + Messages.getString("RowDataDynamic.4") + Messages.getString("RowDataDynamic.5") + Messages.getString("RowDataDynamic.6") + this.owner.getPointOfOrigin()));
        }
    }
}

此代码无条件获取所有其余数据,仅用于记录我未获取的记录数。真的很奇怪。如果附加了记录器,那将是合理的。但在我的例子中,这段代码计算了 30 秒内未获取的行,并且……什么都不做。这个问题我无法解决,因为没有参数可以告诉代码不要计算行数。

现在我不知道下一步该做什么。查询时间对我来说很慢。例如,php 的 mysql 驱动程序在 0.0004-0.001 秒内执行此查询。

那么使用 mysql-connector for Java 的人,请告诉我你有没有遇到这些问题?如果没有,您能否发布任何示例我应该怎么做才能绕过上述问题?也许您使用其他连接器。那么请告诉我,该怎么做?

最佳答案

你的 SQL 查询说

SELECT * FROM test ORDER BY id

您通过该查询指示您的 MySQL 服务器序列化您的 test 表的每一行每一列并将其发送到你的 Java 程序。所以,MySQL服从了。你有一张大 table 。所以你对 MySQL 的指令需要时间。是的,表格中的行越多,花费的时间就越长。这不是 JDBC 或驱动程序的问题;这是您使用的 SQL 的问题。

从您的示例代码看来,您想要一列——名为 value——来自表中的一行——第一行。您可以使用此 SQL 语句完成此操作:

 SELECT value FROM test ORDER BY id LIMIT 1

如果您的 id 列是您表的主键,这会很快。

SQL 的重点 是允许您的表包含如此多的行,以至于在短时间内将它们全部提取到您的 Java(或其他)程序中是不合理的。这就是 SQL 具有 WHERELIMIT 子句的原因。

关于java - SELECT 上的 JDBC 连接器太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44069889/

有关java - SELECT 上的 JDBC 连接器太慢的更多相关文章

  1. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  2. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  3. ruby-on-rails - rspec should have_select ('cars' , :options => ['volvo' , 'saab' ] 不工作 - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request

  4. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  5. ruby-on-rails - openshift 上的 rails 控制台 - 2

    我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

  6. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  7. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  8. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用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

  9. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  10. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

随机推荐