groovy sql eachRow и метод строк

Я новичок в grails и groovy. Может ли кто-нибудь объяснить мне разницу между этими двумя методами groovy sql

sql.eachRow
sql.rows

кроме того, что более эффективно?

Я работаю над приложением, которое извлекает данные из базы данных (набор результатов очень огромен) и записывает их в CSV-файл или возвращает формат JSON.

мне было интересно, какой из двух методов, упомянутых выше, использовать для ускорения и эффективности процесса.

3 ответов


может ли кто-нибудь объяснить мне разница между этими двумя заводной методы sql sql.eachRow в SQL.строки

трудно точно сказать, какие 2 метода вы ссылаетесь на 2, потому что существует большое количество перегруженных версий каждого метода. Однако, во всех случаях eachRow ничего не возвращает

void eachRow(String sql, Closure closure)

, тогда как rows возвращает список строк

List rows(String sql) 

если вы используете eachRow закрытие прошло в качестве второй параметр должен обрабатывать каждую строку, например,

sql.eachRow("select * from PERSON where lastname = 'murphy'") { row ->
    println "$row.firstname"
}

если вы используете rows строки возвращаются, и поэтому должны обрабатываться вызывающим абонентом, например

rows("select * from PERSON where lastname = 'murphy'").each {row ->
    println "$row.firstname"        
}

кроме того, что более эффективно?

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

  • что оборудование, которое вы используете
  • какой JVM вы нацелены
  • какую версию Groovy вы используете
  • какие параметры вы будете передает
  • является ли этот метод узким местом для производительности вашего приложения

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

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


Если мы отложим незначительные синтаксические различия, есть одно различие, которое кажется важным. Рассмотрим

sql.rows("select * from my_table").each { row -> doIt(row) }

vs

sql.eachRow("select * from my_table") { row -> doIt(row) }

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

EachRow с другой стороны открывает соединение и при сохранении он open выполняет закрытие для каждой строки. Если закрытие работает с базой данных и требует другого соединения, код будет использовать два соединения из пула одновременно. Соединение, используемое eachRow, освобождается после итерации всех результирующих строк. Кроме того, если вы не выполняете никаких операций с базой данных, но закрытие занимает некоторое время, вы будете блокировать одно подключение к базе данных до завершения eachRow.

Я не уверен на 100%, но, возможно, eachRow позволяет не хранить все результирующие строки в памяти, а обращаться к ним через курсор-это может зависеть от драйвера базы данных.

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


Они отличаются только подписью - оба набора результатов поддержки paging, поэтому оба будут эффективными. Используйте то, что соответствует вашему коду.