Измерьте временную производительность набора результатов по SQL-запросам

#sql #jdbc #resultset #duckdb

Вопрос:

У меня есть некоторые вопросы, касающиеся понимания «Набора результатов». Если я хочу измерить время производительности, необходимое для выполнения запроса, нужно ли мне повторять набор результатов —> while(rs.next ()), поскольку фактический набор результатов уже содержит все результаты? Или это больше похоже на буфер, который при повторении набора результатов просто генерируется какой-то кортеж?

 Statement b = conn.createStatement();
ResultSet rs2 = b.executeQuery("Select o_orderkey, o_orderstatus, o_orderdate, o_orderpriority, o_comment from orders");
while(rs2.next()){
    int okey=rs2.getInt(1);
    String st=rs2.getString(2);
    Date dt=rs2.getDate(3);
    String pr=rs2.getString(4);
    String co=rs2.getString(5);
}
long endTime = System.currentTimeMillis();
System.out.println(i ". DuckDB "   (endTime- startTime)  " ms");
 

Для этого примера существует огромная разница в производительности. Когда я измеряю только время, необходимое для построения набора результатов без цикла while, это всего лишь часть времени. Вот почему я подумал, что это может зависеть от базы данных, поскольку DuckDB векторизуется в базе данных.

Мой вопрос теперь в том, какой путь является правильным, когда я хочу только иметь время, необходимое для ответа на запрос?

Комментарии:

1. Я полагаю, что под капотом JDBC откроет курсор базы данных, который затем будет повторять набор результатов по мере его обработки.

2. Хорошо, это означает, что вы думаете, что на самом деле есть необходимость прокручивать результирующий набор. Я правильно вас понял?

3. Более или менее, да, весь результирующий набор не поступает в Java сразу.

Ответ №1:

Я не знаю DuckDB, поэтому не могу ответить конкретно за эту систему баз данных.

В общем, простого ответа на этот вопрос не существует. Некоторые драйверы JDBC будут извлекать все строки при выполнении запроса и только затем возвращать результирующий набор, в то время как некоторые другие драйверы JDBC будут извлекать строки только при повторении результирующего набора. Драйверы JDBC могут паковать строки, поэтому несколько вызовов next() могут быть выполнены из одного пакета, и только в том случае, если пакет (почти) пуст, они могут выполнять обратный вызов в базу данных для каждого вызова next() . Теоретически возможно даже, что каждый getXXX из них совершит обратный переход к базе данных (хотя это редко встречается или применимо только для больших двоичных объектов).

Другими словами, поведение зависит от систем баз данных и их драйверов, а также может зависеть от того, находитесь ли вы в режиме автоматической фиксации или нет, используете обновляемый или прокручиваемый набор результатов и, возможно, других факторов (конфигурация драйвера, версия системы базы данных и т. Д.).

Короче говоря, учитывая, что поведение меняется, единственный верный способ-измерить его при выполнении и извлечении всех строк.

Ответ №2:

DuckDB использует векторизованный механизм выполнения, который позволяет обрабатывать потоковые запросы. Если у вас нет полностью материализованного результата запроса, это означает, что каждый раз, когда вы выполняете следующий (), вы будете получать следующий пакет результатов (т. Е. вы будете выполнять план запроса для следующих 1024 элементов вашей таблицы).

Кроме того, для создания набора данных java требуются некоторые затраты на преобразование, так как вам придется выполнить преобразование типов.

Если вы хотите провести тест java, я бы сказал, что полное использование результатов пакетной обработки-это правильный путь, если вы делаете то же самое с другими системами, с которыми вы сравниваете: -)