PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Защо дори да използвате *DB.exec() или подготвени изрази в Golang?

„Защо дори да използвате db.Exec()“:

Вярно е, че можете да използвате db.Exec и db.Query взаимозаменяемо за изпълнение на едни и същи sql оператори, но двата метода връщат различни типове резултати. Ако се реализира от драйвера, резултатът се връща от db.Exec може да ви каже колко реда са били засегнати от заявката, докато db.Query вместо това ще върне обекта rows.

Например, да кажем, че искате да изпълните DELETE изявление и искате да знаете колко реда са били изтрити от него. Можете да го направите по правилния начин:

res, err := db.Exec(`DELETE FROM my_table WHERE expires_at = $1`, time.Now())
if err != nil {
    panic(err)
}

numDeleted, err := res.RowsAffected()
if err != nil {
    panic(err)
}
print(numDeleted)

или по-подробният и обективно по-скъп начин:

rows, err := db.Query(`DELETE FROM my_table WHERE expires_at = $1 RETURNING *`, time.Now())
if err != nil {
    panic(err)
}
defer rows.Close()

var numDelete int
for rows.Next() {
    numDeleted += 1
}
if err := rows.Err(); err != nil {
    panic(err)
}
print(numDeleted)

Има трети начин, по който можете да направите това с комбинация от postgres CTEs, SELECT COUNT , db.QueryRow и row.Scan но не мисля, че е необходим пример, за да покаже колко неразумен би бил подходът в сравнение с db.Exec .

Друга причина да използвате db.Exec през db.Query е когато не ви пука за върнатия резултат, когато всичко, от което се нуждаете, е да изпълните заявката и да проверите дали е имало грешка или не. В такъв случай можете да направите това:

if _, err := db.Exec(`<my_sql_query>`); err != nil {
    panic(err)
}

От друга страна, не можете (можете, но не трябва) да правите това:

if _, err := db.Query(`<my_sql_query>`); err != nil {
    panic(err)
}

Правейки това, след кратко време програмата ви ще изпадне в паника с грешка, която казва нещо подобно на too many connections open . Това е така, защото изхвърляте върнатите db.Rows стойност, без първо да правите задължителното Close извикайте го и така в крайна сметка броят на отворените връзки нараства и в крайна сметка достига лимита на сървъра.

"или подготвени изявления на Голанг?":

Не мисля, че цитираната от теб книга е вярна. Поне за мен изглежда като дали db.Query или не call създава нов подготвен оператор всеки път, зависи от драйвера, който използвате.

Вижте например тези две секции на queryDC (неекспортиран метод, извикан от db.Query ):без подготвено изявление и с подготвено изявление.

Независимо дали книгата е правилна или не db.Stmt създадено от db.Query ще бъде, освен ако не се извършва някакво вътрешно кеширане, изхвърлено, след като затворите върнатите Rows обект. Ако вместо това извикате ръчно db.Prepare и след това кеширайте и използвайте повторно върнатия db.Stmt можете потенциално да подобрите производителността на заявките, които трябва да се изпълняват често.

За да разберете как подготвеното изявление може да се използва за оптимизиране на производителността, можете да разгледате официалната документация:https://www.postgresql.org/docs/current/static/sql-prepare.html




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Не може да се свърже с Postgres чрез PHP, но може да се свърже от командния ред и PgAdmin на друга машина

  2. Как Sinh() работи в PostgreSQL

  3. входният файл изглежда е дъмп на текстов формат. Моля, използвайте psql

  4. Създайте централна таблица с PostgreSQL

  5. Защо итерацията през голям Django QuerySet консумира огромни количества памет?