Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

O MySQL Connector/J armazena em buffer as linhas ao transmitir um ResultSet?


Isso acontece, pelo menos às vezes. Testei o comportamento do MySQL Connector/J versão 5.1.37 usando o Wireshark. Para a mesa...
CREATE TABLE lorem (
    id INT AUTO_INCREMENT PRIMARY KEY,
    tag VARCHAR(7),
    text1 VARCHAR(255),
    text2 VARCHAR(255)
    )

... com dados de teste ...
 id  tag      text1            text2
---  -------  ---------------  ---------------
  0  row_000  Lorem ipsum ...  Lorem ipsum ...
  1  row_001  Lorem ipsum ...  Lorem ipsum ...
  2  row_002  Lorem ipsum ...  Lorem ipsum ...
...
999  row_999  Lorem ipsum ...  Lorem ipsum ...

(where both `text1` and `text2` actually contain 255 characters in each row)

... e o código ...
try (Statement s = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY)) {
    s.setFetchSize(Integer.MIN_VALUE);
    String sql = "SELECT * FROM lorem ORDER BY id";
    try (ResultSet rs = s.executeQuery(sql)) {

... imediatamente após o s.executeQuery(sql) – ou seja, antes de rs.next() é até chamado – o MySQL Connector/J recuperou as primeiras ~140 linhas da tabela.

Na verdade, ao consultar apenas a tag coluna
    String sql = "SELECT tag FROM lorem ORDER BY id";

O MySQL Connector/J recuperou imediatamente todas as 1000 linhas, conforme mostrado pela lista Wireshark de quadros de rede:



O quadro 19, que enviou a consulta ao servidor, ficou assim:



O servidor MySQL respondeu com o frame 20, que começou com ...



... e foi imediatamente seguido pelo quadro 21, que começou com ...



... e assim sucessivamente até que o servidor tenha enviado o quadro 32, que terminou com



Como a única diferença era a quantidade de informações retornadas para cada linha, podemos concluir que o MySQL Connector/J decide um tamanho de buffer apropriado com base no comprimento máximo de cada linha retornada e na quantidade de memória livre disponível.

O MySQL Connector/J inicialmente recupera o primeiro fetchSize grupo de linhas, então como rs.next() se move através deles, eventualmente recuperará o próximo grupo de linhas. Isso é verdade mesmo para setFetchSize(1) que, aliás, é o caminho para realmente obter apenas uma linha de cada vez.

(Observe que setFetchSize(n) para n>0 requer useCursorFetch=true na URL de conexão. Aparentemente, isso não é necessário para setFetchSize(Integer.MIN_VALUE) .)