Галоўная / Артыкулы

Чысты SQL, Prisma чыра Drizzle: Выбір шара базы дадзеных для безпекі тыпаў і кантролю

Які разніцы ў можлівасцях керування, безпецы типаў і досвядзе для разработчыкаў у прымітным SQL, Prisma і Drizzle на базе PostgreSQL, а таксама практычны спосаб выбору аднаго з іх для аплікацыі на TypeScript.

Выдавец: REACTAPP.TOP15 хв чытання3403 слоў

Крыніцы: Prisma vs Drizzle vs Raw SQL: What Every Backend Developer Should Understand Before Choosing an ORM

Большая частка роботы на бакэндзе пачатваецца з таго, што трэба, каб API адпавядала. Вы налажваете маршруты, дадзеўляеце адзін-два кантролеры, дадзеўляеце механізмы аутантыкацыі і дзеяльнасць мідлвэра, і на час гэта ёсць весь пракцэс. Потым з’яўляецца сложнейшы вопыт: як саме прыкладнэе програма павінна вярбавацца з сваёй базай дадзеных? Раптам з’яўляецца множына тэрмінаў (чысты SQL, драйверы, ORM, з’еднальнікі запытаў, Prisma, Drizzle) і супернечлівыя думкі з усіх бакоў. Дзеякіі інжынеры не будуць вярбавацца ORM. Іншыя кажуць, што Prisma заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заўсёды заў

Перш чым назва якога-небудзь інструмента стане зрозумелай, корыстна ўвесь час стежыць за тым, як запит праходзіць через тыповы задні кант. Хтось адвіязаецца на ваш сайт і нажымае на такі элемент керування, як «Паказаць мой профіль». Гэтыя дзеянні пачынаюцца ў браузеры, праходзяць через ваш API, да шара базы дадзеных, і нарэшце да самай базы дадзеных, прычым раней чым адпаведны адпаведны рэспонс здзейснюе зворачны пат.

Browser
   |
   vExpress API   |
   vDatabase Layer   |
   vPostgreSQL Database   |
   vResponse back to the user

Слой базы дадзэных усередзіне — гэта там, дзе супакоўкі найбольшыя. Ваша прыкладна програма патрабуе якога-небудзь механізма для абмену з базай дадзэных, і існуе тры распашчытныя спосабы: напісанне сырога SQL рукамі, выкарыстоўванне ORM, такога як Prisma, або выкарыстоўванне з’еднанніка запытаў, такога як Drizzle. Кожны з наведзеных нижэй раздзелаў розглядае адны з гэтых спосабаў.

Напісанне SQL рукамі

Найболей прымітны спосаб — гэта таксама і старейшы: вы самі пісаеце SQL. Уявіце сабе простую табліцу корыстнікаў з звычайнымі столбцамі.

users
id
name
email
password

З’явленне адзінаго пользователя ў такім случае ўсё абыдзецца проста.

SELECT *
FROM users
WHERE id = 1;

Паколькі база дадзеных викорыстоўвае SQL як свой адгуковы язык, ніч гэта не перакладаецца пад час прыемы чы рээкспорту. У Node.js з PostgreSQL пакет pg ёсць стандартны спосаб прымыкання запытоў безпасабліва. З яго імпортуецца пул з’яўленняў.

import { Pool } from "pg";

Потым вы насталявляеце пул за дапамогай кантэкстнай зменнай і запускаеце параметрызаваны запыт да яго, чытаючы рэзультуючыя рядкі.

const pool = new Pool({
  connectionString: process.env.DATABASE_URL
});const result = await pool.query(
  "SELECT * FROM users WHERE id = $1",
  [1]
);console.log(result.rows);

Ваш код адресуе SQL-запыт, PostgreSQL яго выконвае, і рэядкі вяртаюцца без жадных проміжных переробак. Калі вы самі пішаеце SQL, вы маеце абсалютны кантроль. Напрыклад, складныя звіты можна стварыць безпосередзя, такія як з’едынэнне корыстнікаў з іх замовленнямі та групаванне для підрахунку колькісці замовленняў кожнага корыстніка.

SELECT
users.name,
COUNT(orders.id)
FROM users
JOIN orders
ON users.id = orders.user_id
GROUP BY users.name;

Для такіх складных аналітичных запитоў рукапісны SQL даслівна важка папрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць паспрабаваць

const result = await pool.query(
`
SELECT *
FROM users
WHERE email=$1
`,
[email]
);

Уявім, што хтось перейменав столбець, змінівши email на email_address. Кожны запит, який выкарыстоўвае гэты столбець, бесшумна перастае працаваць. База дадзенаў негаюча фіксуе такую змяну, але ваш код на TypeScript нічога пра гэта не ведае, пакуль ў часе выканання не выйдзе працэс. Існуе ўсё болей тонкі варіянт таго ж абліку. Спадзяймося, што вы берете першы рядок.

const user = result.rows[0];

Потым вы чытаеце якое-небудзь атрыбут з яго, пры тым дапускаючы памылку.

console.log(user.emial);

Неправільна запісь emial не вызывае жадных прытакоў з боку JavaScript. Вы дазволяеце яе з’явіцца толькі тады, калі гэты рядок выконваецца і спрычынае проблемы для пользователя. Самэўсёлкі гэты тип прытакоў є прычыной існавання ORM.

Што такое ORM на самай справе

ORM — гэта скрацанне ад Object Relational Mapping, якое звучыць грандзяйша, чым ёсць на самай справе. Це проста означае, што існуе мост між вашым мовам програмавання і вашай базай дадзенаў. У замест на тое, каб пісаць запыт вручную,

SELECT *
FROM users
WHERE id=1;

Вы пісаеце ўсё больш на кшталт вызову методу на об’екте.

user.findUnique({
 id: 1
})

ORM берае гэта і на самайм вышэй стварае рэальны SQL, тады ваш код праходзіць через ORM да створанага запыту, а потым да базы дадзеных.

Your TypeScript code
        |
        vORM        |
        vSQL query        |
        vDatabase

Команды выбіраюць ORM-ы, таму што сучасныя прыкладніцы прагнуць не проста спосабу выканання запитоў. Яны хачуць безпекі типаў, рэальных міграцый, калектывавання схем, якое не выклікае неабходнасці запамятаваць кожную табліцу, а таксама значна меншай кількасці повтараючыхся стандартных частак коду. У сучасным свете TypeScript найбольш популярныя імены — Prisma, Drizzle, TypeORM і Sequelize. Адзінакавасць тут сконцентравана на чыстым SQL, Prisma і Drizzle, таму што гэтыя трое падтрымліваюць тое, што насправды важывае для большасці сучасных бэкендов на TypeScript.

Пазнайомства з Prisma

Prisma ўваходзіць у число найбольш обсужваемых ORM-сістэм у экосістэме TypeScript і часта яе называюць першай у будзь-якіх размовах пра сучасныя бэкенды на Node.js. Яго галоўная функцыя — дазволіць прыкладнэй программе на TypeScript вясці са базай дадзенаў за дапамогою звычайнага TypeScript, а не з SQL, які ўсюды розбросаны; кроме таго, ён падтрымлівае PostgreSQL, MySQL, SQLite, SQL Server і MongoDB. Вы пішаеце код на TypeScript, а Prisma ператварае яго на запыты.

TypeScript code
        |
        vPrisma Client        |
        vSQL queries        |
        vDatabase

Тыповая настройка Express, Prisma і PostgreSQL адмініструецца чыста: запыты прыходзяць через API, праходзяць через шар служб і доходзяць да базы дадзеных праз Prisma Client.

Client
  |
  vExpress API  |
  vService Layer  |
  vPrisma Client  |
  vPostgreSQL Database

Prisma Client — гэта та частка, яка выканае рэальную работу: практычны мост между вашым кодам бэкэнда і базайнам дадзеных, якая знаходзіцца за яго. Усё пачынаецца з аднаго файла schema.prisma, які описвае весья структуру базайнам дадзеных у аднам месцы. Напрыклад, модель выкарыстоўнікай заявляе чатыры столбцы з адзінаковым типам.

model User {
  id       Int    @id @default(autoincrement())
  name     String
  email    String @unique
  password String
}

Этый блакет паведамляе Prisma стварыць табліцу User з гэтымі столбцамі, і Prisma абсалютна разумее, што гэта значыць. У той час як у сырой SQL патрэбна явная запаведзь для стварэння той самай табліцы,

CREATE TABLE users (
 id SERIAL PRIMARY KEY,
 name TEXT,
 email TEXT UNIQUE,
 password TEXT
);

Prisma патрэбна толькі вышэўказаная блок-схема, і ён перакладае яе ў рэальныя змяны базы дадзенаў праз міграцыю. Міграцыя па сутнасці — это запісаная історыя таго, як база дадзенаў змінялася з часам. Падазроўцуймо, што ваша табелю корыстувача спачатку є мінімальная.

User
id
name
email

Чырэць месца пазней вы хочаце дадаць номер тэлефона. У замяне ручнага змены таблыцы вы выканаеце адзін каманду.

npx prisma migrate dev --name add_phone_number

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

const user = await prisma.user.findUnique({
  where:{
    id:1
  }
});

За кулісамі, дзе тыха ўсё ператвараецца на звычны SQL.

SELECT *
FROM users
WHERE id=1;

Вам ніколи не было неабяк трэба самім пісаць SQL-код. Звычныя операцыі таксама інтуітыўна пераадражаюцца: адбіранне дадзеных стае вызывам функциі create, адбіранне всіх дадзеных — вызывам функциі find-many, адкорэктаванне записі — вызывам функциі update з умовайю where, а выдаленне — вызывам функциі delete. Самае важнае, што дае Prisma свою репутацыю, — это безпека типаў. Якщо ваша схема визначае User з ідэнтыфікаторам, іменем і адресай электранай пошты, то падчас запытанняў адбываецца справжніе автадапліўванне для кожнага поля.

const user = await prisma.user.findMany();
user[0].email;

Якша запісаць гэта як user[0].emali, і Prisma разам з TypeScript адзначае гэта ўсё яшчэ до таго, як запускаецца аплікацыя, што з часам дапамагае заўсёды заўсходзіць значныя часы на адлучэнне бягаў. Звычайна, справжнія аплікацыі рэдка калі маюць толькі адну табелю. Спадзяймося, ў пользователя є багато пастак, тады є сторона users і сторона posts, якія з’яўляюцца ў зв’язку за дапамогою user id.

User
id
namePostid
title
userId

Prisma выказвае гэтыя адносіны безпосередна ў схеме, як у модэлі корыстніка,

model User {
 id Int @id @default(autoincrement())

і модель паведамлення, яка паўтараеся да свага корыстніка через аднос.

 name String posts Post[]
}model Post { id Int @id @default(autoincrement()) title String userId Int user User @relation(
 fields:[userId],
 references:[id]
 )}

Зялэнне пользователя разам з яго паспэсламі стае аднам чытальным вызовам, які включае супаўязаныя запісы.

const user = await prisma.user.findUnique({
 where:{
  id:1
 },
 include:{
  posts:true
 }
});

Это вяртае об’ект пользователя з глыбкім масавым паведамленняў, які якраз падходзіць для коду прыкладнага праграмы. Сілы Prisma заключаюцца ў тым, насколькі прыемным ёст кантэкст разработкі, насколькі высока яго безпека типаў у проектах на TypeScript, насколькі адлагоджаныя стаюць міграцыі, насколькі якісная ў яго дакументацыя, і насколькі быстра цэлыя каманда можа прачытаць схему і зрозумець структуру базы дадзенаў.

Эта падчырка не ўжо без компрэсаў. Справжняя, складная абработка даных можа здавацца некамфортной паўстаўна па лепшы SQL, напісаны рукой. Паколькі Prisma так эфектыва маскіруе SQL, разработчыкі, які вучацца толькі Prisma, іноды сталкнуцца з труднасцямі пазней, калі ім патрэбна оптымізацыя на рэвэрсе базы дадзеных. Кроме таго, у пацеку запыту є ўсё ж адна дапаможная ступеня — ад аплікацыі да Prisma, да SQL, да базы дадзеных, у працоўнасці з коротшым маршрутом аплікацыя-SQL-база дадзеных. Для большасці аплікацыяў гэты дапаможны слой не ўтварае проблемы, але важна знать, што ён існуе. Prisma наілучша падходзіць, калі вы ствараеце API на TypeScript, хочаце шырокага развіцця, пераважна патрэбуее стандартных функцый стварання, чытання, апдэйта і выдалення дадзеных, і дужа пакульгуее да досвіду разработчыка, таму ўсё больш стартапаў і продуктав SaaS апіраюцца на яго.

Дзе падходзіць Drizzle

Drizzle — гэта ўсё той жа ORM, які здобыў сэрьязны розвитак у TypeScript, і каб яго зрозумець, пачынаючы з таго, трэба усвядоміць, што Prisma і Drizzle стояць на абсалютна разных філасофіях. Prisma стараецца як можа адводзіць разработчыкаў ад складнасцяў базы дадзенаў. Drizzle займае працоўную позыцыю: ён стараецца трываліць разработчыкаў ближэй да SQL і проста дадае безпеку, якая є у TypeScript. Оба прагнуць таго ж рэзультата — кращага досвіду роботы з базай дадзенаў, але за абсалютна разнымі шляхамі. Drizzle — это лёгкі TypeScript ORM для PostgreSQL, MySQL і SQLite, які акцэнтаваецца на безпецы типаў, выдатнасці, близкасці да SQL і простай архітэктуре. Вы продовжваеце пісаць код на TypeScript, які через Drizzle пераходзіць у запиты і даходзіць да базы дадзенаў.

TypeScript code
        |
        vDrizzle ORM        |
        vSQL query        |
        vDatabase

Якщо разместыць гэтыя два элементы паштоўна адна ля другой, філасофскія разлікі стануць явнымі. Зявленне ўсіх корыстуначаў у Prisma адбываецца так, як паказана нижэй, а SQL-запыт, які гэта стварае, рэдка калі спадае на думку.

const user = await prisma.user.findMany();

Drizzle прасіць чыгульністкі, які больш прыкладнае да рэальнага SQL.

const users = await db
.select()
.from(usersTable);

Вы можете практычна прачытаць працэю базы дадзеных на рэвэле коду. Схемы таксама разныя. Prisma зберагае іх у спецыяльным файле schema.prisma, тады калі Drizzle адзначае схему ў звычным TypeScript, спачатку імпортуяя неабходныя канстракты столбцоў.

import {
 pgTable,
 serial,
 varchar
} from "drizzle-orm/pg-core";

і адзыначэнне таблыцы з ступільнімі столбцамі.

export const users = pgTable("users", { id: serial("id").primaryKey(), name: varchar("name"), email: varchar("email")});

Структура вашай базы дадзэных тады жывець працоўна ў самай базе кода TypeScript, і не трэба выбіраць жаднага дадзейнага схематызму. Кождыя повсякдзенныя операцыі нагадваюць SQL, але выкананыя за дапамою TypeScript: адбыцце дадзеных — цэх вызову з параметрамі, чытанне всіх дадзеных — цэх select з табелю, а фільтрацыя дадае клазу where, створаную за дапамою функцыі для параднасці. Людзі выбіраюць Drizzle з кальколька прычын. Ён справды лёгкі, з мінімумам абстракцый. Усёлякія абстракцыі не заважаюць вашым навыкам SQL, а толькі ўдосконаляюць іх. Ствараныя ім запыты зазвычай є прыгаднымі, адколі між вашымі намерамі і рэзультатам ёсць мінімум перакладачаў. Кроме таго, ён спроектаваны з уважнам да сучасных средаваў выканання, укладаючы ў сябе таксама средавы edge і serverless.

З іншай боку, якщо вы ніколі не вивчалі SQL, Drizzle можа здавацца болей заплутанай на пачатку, чым Prisma, яка зазвычай є лёгшым варыянтам для новачкаў. Ёжыць Drizzle належным чынам абавязкова выкалічвае розумеўце з’еднанняў, адносаў, індэксаў і таго, як працююць запыты, без жадных ухілень ад гэтага. І хоча яго экасистема, дакументацыя і спяльнота ўстойкія, яны застаюцца меньшымі, чым болей развітыя рэшэнні Prisma. Найяснейшы спосаб прыродзіць гэты контраст — такі: з Prisma база дадзенаў спрацоўванае як скупка об’ектаў, і акцэнт ставіцца на досвід разработчыка, тады калі з Drizzle база дадзенаў спрацоўванае больш як сам SQL, і акцэнт пераходзіць да выдатнасці і кантролю.

Тры падходы паўстаюць па боку адна другай

Калі бачыць усе тры, іх архітектуры выступаюць як спектр таго, сколькі слоёў знаходзіцца межы прыкладнам програмам і базай дадзенаў.

Raw SQL:      Application → SQL Query → Database
Prisma:       Application → Prisma Client → SQL → Database
Drizzle:      Application → Drizzle → SQL → Database

Разглянем простую операцыю – пошук пользователя па адресе электранайтовай, утварыч у базе дадзеных з простым таблам корыстнікаў. У чыстам SQL вы надаеце параметрызаваны запыт безпосередна.

const result = await pool.query(
`
SELECT *
FROM users
WHERE email=$1
`,
["rahul@test.com"]
);

У Prisma вы выклікаеце унікальны пошук.

const user =
await prisma.user.findUnique({

Перадача адрэса электранай пасу ў клазе where.

where:{
 <email:"rahul@test.com>"
}});

У Drizzle вы ствараеце сэлект, які обмежваецца равенстваю ў столцы пад назвай email.

const user =
await db
.select()
.from(users)
.where(
 eq(
 users.email,
 "rahul@test.com"
 )
);

Усе трыя ў канцы выдаюць аднаковыя даны. Разлік заключаецца ў тым, насколькі контролю вы хочаце, насколькі абстракцыі вам зручна викорыстоўваць, і насколькі SQL вы вже знаеце. Частая памылка пачатківаўцяў — акцэнтаванне на тым, який з іх ўжоўшы, хоча ў рэальных проектах швальба рэдкая ёсць вынікнуючая прычына. Кращыя запытанні — гэта тое, з чым каманда вже знаеце ся, насколькі насправды складны проект, насколькі моцныя ў всіх знанні пра базы дадзеных, і насколькі складнымі, верагодна, стануць запытанні. Простая SaaS-зялёнка зазвычай добра функцыонуе толькі з Prisma, тады як у застолькі залежных ад базы дадзеных прыкладнасцях Drizzle, або ж чысты SQL у дзеякіх частках, пачынае прадаваць свою корыстнасць.

Ёсць простыя словы, якія можна выказаць, каб паспрацаваць з гэтымі прынцыпамі: крывая навыку ў разы складнейшая для чыстага SQL, найпростейшая для Prisma, а для Drizzle — сярэдняя. Контроль над SQL ў чыстым SQL ў высокім ступені, у Drizzle — таксама высокі, а у Prisma — найнижшы. Безпека типаў у чыстым SQL слабая, але ў Prisma і Drizzle — выключна высокая. Прысохлыя спецыялізаваныя можаўкі ў чыстым SQL і Drizzle ў высокім ступені, а у Prisma — гарныя. Досвід разработчыка ў Prisma ў найкращым ступені, у Drizzle — гарны, а у чыстым SQL — сярэдні. Складныя запыткі лепша пісаць у чыстым SQL і Drizzle, а Prisma знаходзіцца сяродзіні. Чысты SQL адстае ў паводлівасці для пачаткуючых: Prisma лідуе, Drizzle — у сярэдзіні, а чысты SQL — адстае.

Тады калі ж выбіраць?

Чы гэты ORM завжоды павінен быць вашым стандартным выборам? Чыста правда — ні. Калякі іншы інструмент, ORM падходзіць для дзеяных задач, але не падходзіць для іншых, і нічога не падходзіць для кожнага проекту. Чысты SQL знаходзіць свае месца тады, калі трэба максимальны контроль, калі прыложэнне справжна сильна залежыць ад базы дадзенаў, калі запыты становяцца складнымі, або калі працэздатнась не можа быць ніжэй. Аналітычныя платформы, системы стварэння звярненняў та фінансавыя прыложэнні падходзяць, так сама як і ўсё, што перадае вялікія об’ёмы дадзенаў. Звярненне, якое адпавядае на пытанні, напрыклад, скількі кожны кліент купіў за пяць гадоў, а таксама якая у яго сярэжная вартасць замовлення, прыродна легча выразіць безпосередна ў SQL, выбіраючы агрегаты.

SELECT
customers.name,
COUNT(orders.id),
AVG(orders.amount)

і ўз’едыненне, і групаванне для стварэння іх.

FROM customersJOIN ordersON customers.id = orders.customer_idGROUP BY customers.name;

Для такай працы нічы не можа заменіць тое, што можа выразіць SQL. Проблема заключаецца ў тым, што апошнечнае выкарыстанне рукапіснага SQL для всьго ў вялікай базе коду быстра стае неэфектыва, ў результате чаго застаюцца сотні файлаў з запытамі, распакаванымі па розным месцам, а таксама неабходна самостайна стежыць за безпекай типаў. Перспектыва праягоцэнкі працы API Node.js па прыорітетам паказвае, як часта саме база дадзенаў, а не фрэймворк, є месцам справжніх успехоў і недастаткаў.

Prisma частае ўсё ж лепшы выбар, калі вы ствараеце бэкэнд на TypeScript, выконваеце пераважна стандартныя задачі стварэння, чытання, апдэйта і выдалення дадзэнняў, ценіце швальнасць разработкі і координаваеце калькі разработчыкаў у адной базе коду. Гэта стосуецца продуктав SaaS, панэлі адарбытку, API для магазінаў і систем керування контентам, дзе ўседзённыя задачы — стварэнне паўтароў, апдэйт профіля, адправка замовлення чытаў запоўнення дадзэнняў з панэлі. Prisma рэальна падымае продуктыўнасць у такіх сцэнаріях, ператвараючы просты запыт у чысты, чытальны код, які кожны член команды можа за мінуту зрозумець. Drizzle падходзіць тады, калі вы працуеце на TypeScript, вельмі добра ведаеце SQL, цініце выдатнасць і кантроль, і хочаце чагось лёгкага, а не важкага. Ён прывабляе разработчыкаў, якія хочаць абягоўкаў безпекі ад ORM, не чуваючыся занадта аддаленымі ад базы дадзэнняў.

У практыцы багато рэальных проектаў не выбіраюць аднаго-едынственнага падходу. Стартап можа разумна пачаць з простаг шляху: ад Express через Prisma да PostgreSQL.

Express → Prisma → PostgreSQL

Это пачатковы ўзмацненне, якое ўсё ж такі ўсвіядомлена розумна. Пазней, калі продукт расте і з’яўляюцца больш складныя патрэбы ў аналізе даных чы рэпортаванні, команды часта проста дадаюць необработаны SQL-код у адпаведныя часті коду, замест таго каб усунуць Prisma, вялічынкай чаго програма працюе з PostgreSQL як через Prisma, так і через ручна напісаныя запыты.

Application
├── Prisma
└── Raw SQL Queries
        ↓
   PostgreSQL

Іспользованне адзінаго падходу ў всіх месах не ўсёвышнія правіла, якія трэба дапэўніваць, і большасць рэальных кодавых баз у канцы канцоў сумешчае іх. Стартапы часта выбіраюць TypeScript, Prisma і PostgreSQL выключна зарады шырокаспектнасці. Новэйшыя проекты на TypeScript все чышчэй абрацоўваюць Drizzle і яго лёгкі, прыямы да SQL стыль. А большыя системы часта сумешчаюць ORM з неапранутым SQL і спецыяльной оптымізацыяю базы дадзеных, проста таму, што разныя часткі вялікай системы сталкваліся з разнымі проблемамі.

Памылкі, якіх варта ухіліцца

Існуе калькі пры трых распашчах. Першы — це ставленне да ORM як да базы дадзеных. Prisma не ўжо база дадзеных, як і Drizzle; гэтыя інструменты служаюць для доступу да базы дадзеных, незалежна ад таго, чы то PostgreSQL, MySQL чы MongoDB. Другі распашч — це абсалютна адмова ад SQL і працэваўка без яго, выключна з Prisma. Спачатку гэта здаецца эфектыва, але зазвычай гэта прыносіць наследкі: запыты становяцца медленнымі і ўжо немагчыма ўсё разумець, з’еднанні дадзеных стаюць незрозумелымі, а налагоджэнне стае справжнім вызваннем без адпаведнай базы пад абстракцыяй. ORM ніколі не быў створаны для замены SQL; ён працуе вышэй за яго. Трэці распашч — це прагненне да максимальных показнікаў карыстоўнасці. У рэальным жыцці таксама важна карыстоўнасць развівача, і скорачэнне пяці мілісэкунд на запыте, калі розработка стае медленней на тры месцы, рэдкая разважнае рашэнне.

Шлях навучэння, які дае рэзультаты

Пачаткуючы з нуля сьогодні, разумным порядкам є спачатку вивучыць асаліны SQL, укладаючы ў сябе таблицы, первыя ключы, стороннія ключы, з’еднанні, індэксы та транзакцыі, выкорыстоўваючы такі інструмент як PostgreSQL. Потым прабавіце безпосереднюе з’яўленне з драйверам, такім як пакет pg у Node, каб зрозумець, як прыкладны програма вярбуецца з базай з дадзенымі без жадных прыхованых элементаў. Далей перайдзіце да Prisma і адчуўце сябе знайомымі з схемамі, міграціямі, адносамі та ўпэўненасцю ў типах. На завершанні спробавіце Drizzle, каб зрозумець, як выглядае калькулятор запытоў, які прыорітэт дае SQL, а таксама якія є компромісы ў яго продуктывацыі.

Куды це вас прыведзе

Мэтаспэсабельнае адказванне база дадзеных ніколі не было створана для замены SQL. Яна існуе ў тым, каб паспрыяць кращам досвіду разработчыка, і няма нічога важлівейшага за гэта. Справжнія кваліфікаваны разработчык бэкенду не визначаецца тым, наскількі ён добра ведае Prisma чы Drizzle. Це той, хто розумее, як на самай працоўвае база дадзеных, можа напісаць SQL, калі гэта неабходна, ведае, што саме спрасцавляе ORM, і, што таксама важна, ведае, калі мае сэнс вжываць ORM, а калі розумнейшы выбор — рукапісны SQL. Калі з’яўляецца такая яснасць, выбір між гэтымі інструментамі перестае быць спробай здогадацца. Вы пачынаеце прымыкаты рашэнні на адповіднасць практычным патрэбам проекта, а не на тое, што ў даны месяц є популярным.

Спадневанае чытанне

  • Скорачванне навантажэння Prisma і PostgreSQL прытым, прытым, прытым, прытым, прытым, прытым, прытым, прытым, прытым, прытым, прытым, прытым, прытым, прытым, прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым прытым пр