Стоит ли подготовить все запросы в init?

Читая доку насколько я понял то подготовленный запрос потом просто шлёт данные серверу что повышает производительность mysql. Читая доку драйвера мускуля я узнал что он автоматом делает пул коннектов. И мне пришло в голову сделать глобальный map (для пакета) и в init определить в этот мап все запросы (Prepare), а потом через хелпер получать обьект запроса и просто отправлять данные (Exec).

Стоит вообще так делать или же по всему коду пихать Prepare ?
Так как меня не могут понять вот что я описал
package main

import (
	"database/sql"
	"log"

	_ "github.com/go-sql-driver/mysql"
	"github.com/v-grabko/Core/Net/RPC/TCP/Server"
)

var DB *sql.DB
var P map[string]*sql.Stmt

func init() {
	db, err := sql.Open("mysql", "root:parsh888@tcp(127.0.0.1:3306)/AuthService")
	if err != nil {
		log.Fatal(err)
	}
	db.SetMaxIdleConns(50)
	P = make(map[string]*sql.Stmt)
	P["users"], err = db.Prepare("INSERT INTO users(login, email, pass) VALUES( ?, ?, ?)")
	if err != nil {
		log.Fatalf(err.Error())
	}

	DB = db

}

func main() {
	Server.Add("Save", Save)
	Server.Run("", "5000", "password")
}

func Save(ps map[string]string) map[string]string {
	var id int
	err := DB.QueryRow("SELECT id FROM users WHERE login=? AND email=?", ps["login"], ps["email"]).Scan(&id)
	switch {
	case err == sql.ErrNoRows:

		_, err = P["users"].Exec(ps["login"], ps["email"], ps["pass"])
		if err != nil {
			panic(err.Error())
		}
		ps["code"] = "1"
		ps["message"] = "Ok"
	case err != nil:
		log.Println(err)
		ps["code"] = "500"
		ps["message"] = "Ошибка сервера"
	default:
		ps["code"] = "2"
		ps["message"] = "Такой пользователь уже есть"
	}

	return ps
}
  • Вопрос задан
  • 523 просмотра
Решения вопроса 2
index0h
@index0h
PHP, Golang. https://github.com/index0h
Со всей силы не стоит. Базовая инициализация приложения не должна (по хорошему) иметь ничего общего с вашей бизнес логикой (БЛ). В вашем случае это грубое нарушение SOLID (SRP).
Пример из серии "что-то пошло не так": ваш подготовленный запрос в процессе выполнения изменился, код его использующий будет ожидать старого поведения, но отвалится (это в лучшем случае) только после выполнения запроса, а там может быть что угодно. Как результат: поведение методов, использующих эти запросы меняется, без изменения их кода. Подобные ошибки ищутся долго.

-- upd --

Глобальные публичный переменные, как правило, это плохая идея)) Что вы будете делать, если у вас появится еще одно подключение к БД? Переписывать весь код?

У вас функция Save делает select, зачем? Это ж явное противоречие названию

Что касается подключения к БД - рекомендую вынести это в файл настроек, либо флаг запуска.
Ответ написан
@mantyr
Пишу много Golang кода с удовольствием:)
Прежде чем использовать подготовленные запросы прочитайте это:
- go-database-sql.org/prepared.html
- go-database-sql.org/surprises.html

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

Если вам важно увеличить пропускную способность простых INSERT то посмотрите в сторону HandlerSocket, уверен под Golang оно уже должно было появиться, если нету - сможете реализовать самостоятельно, протокол не особо сложный.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
sim3x
@sim3x
Зависит от того какое колличество из подготовленных запросов осуществляется
Если большее -- использовать View СУБД

но лучше использовать lazy методику -- самый быстрый запрос, тот который не нужно исполнять
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы