我正在使用Akka Streams和Slick查询一个大的MySQL表,但它失败了WebViewClient wvc = new WebViewClient() {
/* @Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
if (!progressDialog.isShowing()) {
progressDialog.show();
}
return super.shouldOverrideUrlLoading(view, url1);
}
@Override
public void onPageFinished(WebView view, String url) {
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
*/
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
try {
DefaultHttpClient client = new DefaultHttpClient();
Utility.printMessage("url inside..." + url);
HttpPost httpPost = new HttpPost("http://drive.google.com/viewerng/viewer?embedded=true&url=" + url1);
Utility.printMessage("url after..." + "http://drive.google.com/viewerng/viewer?embedded=true&url=" + url1);
httpPost.setHeader("x-csrf-token", Utility.getToken(context));
HttpResponse httpReponse = client.execute(httpPost);
Header contentType = httpReponse.getEntity().getContentType();
Header encoding = httpReponse.getEntity().getContentEncoding();
InputStream responseInputStream = httpReponse.getEntity().getContent();
String contentTypeValue = null;
String encodingValue = null;
if (contentType != null) {
contentTypeValue = contentType.getValue();
}
if (encoding != null) {
encodingValue = encoding.getValue();
}
return new WebResourceResponse(contentTypeValue, encodingValue, responseInputStream);
} catch (IOException e) {
//return null to tell WebView we failed to fetch it WebView should try again.
return null;
}
}
};
。似乎Slick正在将所有结果加载到内存中(如果查询仅限于几行,则不会失败)。为什么会这样,解决方案是什么?
OutOfMemoryError
答案 0 :(得分:2)
注意:某些数据库系统可能需要以某种方式设置会话参数以支持流式传输,而不会在客户端的内存中同时缓存所有数据。例如,PostgreSQL需要
.withStatementParameters(rsType = ResultSetType.ForwardOnly, rsConcurrency = ResultSetConcurrency.ReadOnly, fetchSize = n)
(具有所需的页面大小n
)和.transactionally
才能进行正确的流式传输。
换句话说,为了防止数据库将所有查询结果加载到内存中,可能需要额外的配置。此配置取决于数据库。 MySQL documentation声明如下:
默认情况下,ResultSet完全检索并存储在内存中。在大多数情况下,这是最有效的操作方式,并且由于MySQL网络协议的设计,更容易实现。如果您正在使用具有大量行或大值的ResultSet并且无法在JVM中为所需内存分配堆空间,则可以告诉驱动程序一次将结果流回一行。
要启用此功能,请按以下方式创建
Statement
实例:stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); stmt.setFetchSize(Integer.MIN_VALUE);
只读的只读结果集与提取大小
Integer.MIN_VALUE
的组合用作驱动程序逐行流式传输结果集的信号。
在Slick中设置上述配置:
import slick.jdbc._
val query =
sql"select my_text from my_table".as(GetResult(r => r.nextString()))
.withStatementParameters(
rsType = ResultSetType.ForwardOnly,
rsConcurrency = ResultSetConcurrency.ReadOnly,
fetchSize = Int.MinValue
)//.transactionally <-- I'm not sure whether you need ".transactionally"
val responses: Source[String, NotUsed] = Slick.source(query)