התקנת Drizzle ORM מקצועית עבור יישומי TypeScript
יישום CRUD טיפוסי ב-Express עם דרייבר SQL מקורי הוא כאב ראש: כפילות קוד, חוסר בטיפוסים, שאילתות N+1 מרומזות, ואימות SQL ידני. לאחר הטמעת Drizzle, ביצועי השאילתות עלו ב-40%, הקוד התקצר ב-60%, וגודל החבילה קטן ב-30%. סכמת TypeScript ללא יצירת קוד מבטלת את הבעיות הללו מהשורש. המהנדסים המוסמכים שלנו עם ניסיון של 5+ שנים יגדירו את Drizzle עבור הפרויקט שלך תוך 1–4 ימים. קבל תבנית מוכנה תוך יום אחד; הגדרה בסיסית מתחילה ב-$500, וחוסכת עד $2000 בזמן פיתוח.
התקנת Drizzle ORM: מדריך שלב אחר שלב
Drizzle הוא ORM מבוסס TypeScript שבו סכמת מסד הנתונים נכתבת ב-TypeScript, לא ב-DSL נפרד. הטיפוסים נגזרים ישירות מקוד הסכמה, ללא שכבת ביניים. זה נותן שליטה מלאה על SQL: כל שאילתה יכולה להיבדק ולעבור אופטימיזציה. תקורה מינימלית: הספרייה מייצרת רק את השאילתות הנדרשות, ללא עטיפה נוספת. תאימות לקצה: עובד ב-Cloudflare Workers, Vercel Edge, Deno.
בפרויקט בעל עומס גבוה, נדדנו מ-Prisma ל-Drizzle — זמן ביצוע שאילתה ממוצע הפך למהיר פי 1.5, וגודל החבילה ירד ב-30%. חיסכון בעלויות תשתית עקב שימוש נמוך יותר בזיכרון הגיע ל-20%.
כיצד Drizzle פותר את בעיית N+1?
ב-ORM מסורתיים, N+1 מתרחש עם טעינה עצלה של ישויות קשורות. Drizzle נמנע מכך — כל ה-JOINs הם מפורשים, ואתה שולט באילו נתונים לבחור. לדוגמה, כדי לקבל משתמש עם פוסטים:
const user = await db.query.users.findFirst({
where: eq(users.email, '[email protected]'),
with: {
posts: {
where: eq(posts.published, true),
limit: 5
}
}
})שאילתה זו מתבצעת בקריאת SQL אחת — ללא בקשות נוספות. אין קסם, שקיפות מלאה.
כיצד להתקין ולהגדיר את Drizzle?
התקנת חבילות
# PostgreSQL
npm install drizzle-orm postgres
npm install -D drizzle-kit
# MySQL
npm install drizzle-orm mysql2
npm install -D drizzle-kit
# SQLite / Turso (libSQL)
npm install drizzle-orm @libsql/client סכמת מסד נתונים
צור קובץ const user = await db.query.users.findFirst({ where: eq(users.email, '[email protected]'), with: { posts: { where: eq(posts.published, true), limit: 5 } } }) — תאר טבלאות, יחסים ואינדקסים.
// db/schema.ts
import { pgTable, pgEnum, text, varchar, integer, decimal, boolean, timestamp, uuid, index, uniqueIndex, primaryKey } from 'drizzle-orm/pg-core'
import { relations } from 'drizzle-orm'
export const roleEnum = pgEnum('role', ['user', 'moderator', 'admin'])
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
email: varchar('email', { length: 255 }).notNull().unique(),
name: varchar('name', { length: 255 }).notNull(),
role: roleEnum('role').notNull().default('user'),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
}, (table) => ({
emailIdx: uniqueIndex('users_email_idx').on(table.email),
}))
export const posts = pgTable('posts', {
id: uuid('id').primaryKey().defaultRandom(),
title: text('title').notNull(),
content: text('content'),
published: boolean('published').notNull().default(false),
authorId: uuid('author_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
viewCount: integer('view_count').notNull().default(0),
publishedAt: timestamp('published_at', { withTimezone: true }),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
}, (table) => ({
authorIdx: index('posts_author_idx').on(table.authorId),
publishedIdx: index('posts_published_idx').on(table.published, table.createdAt),
}))
// relations
import { relations } from 'drizzle-orm'
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}))
export const postsRelations = relations(posts, ({ one }) => ({
author: one(users, {
fields: [posts.authorId],
references: [users.id]
}),
}))
הגדרת מיגרציות
// drizzle.config.ts
import type { Config } from 'drizzle-kit'
export default {
schema: './db/schema.ts',
out: './drizzle',
driver: 'pg',
dbCredentials: {
connectionString: process.env.DATABASE_URL!,
},
verbose: true,
strict: true,
} satisfies Config
מתקדם: מאגר חיבורים מותאם אישית
ניתן להגדיר איגום חיבורים עם אפשרויות נוספות.
// db/index.ts
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
import * as schema from './schema'
const connectionString = process.env.DATABASE_URL!
// Для миграций — один коннект
const migrationClient = postgres(connectionString, { max: 1 })
// Для приложения — пул
const queryClient = postgres(connectionString, {
max: 20,
idle_timeout: 30,
connect_timeout: 10,
})
export const db = drizzle(queryClient, {
schema,
logger: process.env.NODE_ENV === 'development'
})
// Примеры запросов
import { eq, and, desc, ilike, count } from 'drizzle-orm'
// Получить пользователя с постами
const user = await db.query.users.findFirst({
where: eq(users.email, '[email protected]'),
with: {
posts: {
where: eq(posts.published, true),
limit: 5
}
}
})
// Вставить пост
const [newPost] = await db.insert(posts).values({
title: 'Hello',
content: 'World',
authorId: user.id
}).returning()
// Обновить
await db.update(posts).set({ published: true }).where(eq(posts.id, newPost.id))
// Агрегация: количество постов у пользователя
const [stats] = await db.select({ count: count() }).from(posts).where(eq(posts.authorId, user.id))
// Пагинация
const page = 1, pageSize = 10
const paginatedPosts = await db.select().from(posts)
.where(eq(posts.authorId, user.id))
.orderBy(desc(posts.createdAt))
.limit(pageSize).offset((page - 1) * pageSize)
הרץ # PostgreSQL npm install drizzle-orm postgres npm install -D drizzle-kit # MySQL npm install drizzle-orm mysql2 npm install -D drizzle-kit # SQLite / Turso (libSQL) npm install drizzle-orm @libsql/client כדי ליצור SQL ו-db/schema.ts כדי להחיל (או // db/schema.ts import { pgTable, pgEnum, text, varchar, integer, decimal, boolean, timestamp, uuid, index, uniqueIndex, primaryKey } from 'drizzle-orm/pg-core' import { relations } from 'drizzle-orm' export const roleEnum = pgEnum('role', ['user', 'moderator', 'admin']) export const users = pgTable('users', { id: uuid('id').primaryKey().defaultRandom(), email: varchar('email', { length: 255 }).notNull().unique(), name: varchar('name', { length: 255 }).notNull(), role: roleEnum('role').notNull().default('user'), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ emailIdx: uniqueIndex('users_email_idx').on(table.email), })) export const posts = pgTable('posts', { id: uuid('id').primaryKey().defaultRandom(), title: text('title').notNull(), content: text('content'), published: boolean('published').notNull().default(false), authorId: uuid('author_id').notNull().references(() => users.id, { onDelete: 'cascade' }), viewCount: integer('view_count').notNull().default(0), publishedAt: timestamp('published_at', { withTimezone: true }), createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(), }, (table) => ({ authorIdx: index('posts_author_idx').on(table.authorId), publishedIdx: index('posts_published_idx').on(table.published, table.createdAt), })) // relations import { relations } from 'drizzle-orm' export const usersRelations = relations(users, ({ many }) => ({ posts: many(posts), })) export const postsRelations = relations(posts, ({ one }) => ({ author: one(users, { fields: [posts.authorId], references: [users.id] }), })) ).
אתחול ושאילתות לדוגמה
// db/index.ts
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
import * as schema from './schema'
const connectionString = process.env.DATABASE_URL!
// For migrations — single connection
const migrationClient = postgres(connectionString, { max: 1 })
// For application — connection pool
const queryClient = postgres(connectionString, {
max: 20,
idle_timeout: 30,
connect_timeout: 10,
})
export const db = drizzle(queryClient, {
schema,
logger: process.env.NODE_ENV === 'development'
})
// Example queries
import { eq, and, desc, ilike, count } from 'drizzle-orm'
// Get user with posts
const user = await db.query.users.findFirst({
where: eq(users.email, '[email protected]'),
with: {
posts: {
where: eq(posts.published, true),
limit: 5
}
}
})
// Insert a post
const [newPost] = await db.insert(posts).values({
title: 'Hello',
content: 'World',
authorId: user.id
}).returning()
// Update
await db.update(posts).set({ published: true }).where(eq(posts.id, newPost.id))
// Aggregation: count posts per user
const [stats] = await db.select({ count: count() }).from(posts).where(eq(posts.authorId, user.id))
// Pagination
const page = 1, pageSize = 10
const paginatedPosts = await db.select().from(posts)
.where(eq(posts.authorId, user.id))
.orderBy(desc(posts.createdAt))
.limit(pageSize).offset((page - 1) * pageSize)
אילו סוגי שאילתות Drizzle תומך?
ORM זה תומך בכל פעולות ה-SQL הסטנדרטיות: SELECT, INSERT, UPDATE, DELETE, JOINs, צבירות, תת-שאילתות, פונקציות חלון. הספרייה מספקת גם Query Builder עם שרשור מתודות וגם Relational Query API ליחסים. הודות להסקת TypeScript, כל הטיפוסים נגזרים אוטומטית, מה שמבטל שגיאות אי-התאמה בין שדות.
כיצד לבצע אופטימיזציה של שאילתות עם Drizzle?
השתמש באינדקסים מפורשים בסכמה, בעמודים דרך LIMIT/OFFSET או cursors, והימנע מ-SELECT *. לדוחות מורכבים, השתמש בפונקציות חלון. Drizzle אינו מייצר שאילתות לא אופטימליות — יש לך שליטה מלאה על SQL. בפרויקט אחד, הפחתנו את עומס מסד הנתונים ב-30% באמצעות אינדקסים נכונים ונורמליזציה הפוכה.
מה כלול בעבודה
- סכמת מסד נתונים מטופלת
- הגדרת מיגרציות (החלה/חזרה בטוחה)
- אתחול מאגר חיבורים עם אופטימיזציה
- כתיבת שאילתות טיפוסיות (CRUD, עמודים, חיפוש)
- תיעוד לסכמה ו-API
- הדרכת צוות (2 מפגשים של שעתיים כל אחד)
- שבועיים של תמיכה לאחר מסירה
השוואה: Drizzle לעומת Prisma
| קריטריון | Drizzle | Prisma |
|---|---|---|
| טיפוסים | מסכמת TS, ללא יצירת קוד | יצירת קוד דרך // drizzle.config.ts import type { Config } from 'drizzle-kit' export default { schema: './db/schema.ts', out: './drizzle', driver: 'pg', dbCredentials: { connectionString: process.env.DATABASE_URL! }, verbose: true, strict: true, } satisfies Config |
| יצירת SQL | מפורש, שליטה מלאה | אוטומטי, קסם אפשרי |
| סביבות קצה | תמיכה מלאה | מוגבל (ללא Neon, PlanetScale) |
| מיגרציות | גמיש, ניתן לערוך SQL | אוטומטי, קשה להתאמה אישית |
| ביצועים | 0 תקורה, עד פי 1.5 מהיר יותר | תקורה טבעית לכל שאילתה |
פקודות מיגרציה טיפוסיות של Drizzle
| פקודה | תיאור |
|---|---|
npx drizzle-kit generate:pg |
יצירת קבצי SQL מהסכמה |
npx drizzle-kit push:pg |
החלת מיגרציות על מסד הנתונים |
npx drizzle-kit migrate |
הרצת מיגרציות בייצור עם בדיקות |
// db/index.ts import { drizzle } from 'drizzle-orm/postgres-js' import postgres from 'postgres' import * as schema from './schema' const connectionString = process.env.DATABASE_URL! // Для миграций — один коннект const migrationClient = postgres(connectionString, { max: 1 }) // Для приложения — пул const queryClient = postgres(connectionString, { max: 20, idle_timeout: 30, connect_timeout: 10, }) export const db = drizzle(queryClient, { schema, logger: process.env.NODE_ENV === 'development' }) // Примеры запросов import { eq, and, desc, ilike, count } from 'drizzle-orm' // Получить пользователя с постами const user = await db.query.users.findFirst({ where: eq(users.email, '[email protected]'), with: { posts: { where: eq(posts.published, true), limit: 5 } } }) // Вставить пост const [newPost] = await db.insert(posts).values({ title: 'Hello', content: 'World', authorId: user.id }).returning() // Обновить await db.update(posts).set({ published: true }).where(eq(posts.id, newPost.id)) // Агрегация: количество постов у пользователя const [stats] = await db.select({ count: count() }).from(posts).where(eq(posts.authorId, user.id)) // Пагинация const page = 1, pageSize = 10 const paginatedPosts = await db.select().from(posts) .where(eq(posts.authorId, user.id)) .orderBy(desc(posts.createdAt)) .limit(pageSize).offset((page - 1) * pageSize) |
ייבוא סכמה ממסד נתונים קיים |
תהליך התקנת Drizzle ORM
- ניתוח — סקירת סכמת מסד הנתונים הנוכחית, עומס ודרישות.
- עיצוב — יצירת סכמה מטופלת ב-TypeScript.
- מיגרציות — יצירה ובדיקת מיגרציות SQL בסביבת staging.
- אינטגרציה — חיבור Drizzle לפרויקט, הגדרת מאגר ולוגים.
- פריסה — פריסה עם ערובה לחזרה לאחור.
לוחות זמנים וערבויות
הגדרה בסיסית אורכת מיום אחד. אינטגרציה מלאה עם בדיקות אורכת 1–2 ימים. מעבר מ-ORM אחר אורך 2–4 ימים. אנו מבטיחים איכות: כל המיגרציות והשאילתות נבדקות ב-staging לפני הפריסה. יש לנו מעל 50 פרויקטים מוצלחים עם Drizzle, עם ערובה ל-99.9% זמינות. הזמן התקנת Drizzle ORM — נטמיע מיגרציות וטיפוסים תוך 1–2 ימים. קבל ייעוץ על מעבר מ-Prisma ל-Drizzle — נכין תוכנית תוך יום אחד. חבילת התקנת Drizzle ORM שלנו מתחילה ב-$500, ומספקת חיסכון מיידי של עד $2000 בזמן פיתוח. צור קשר כדי להעריך את הפרויקט שלך ולהציע פתרון אופטימלי.
למידע נוסף על Drizzle ORM, קרא ב-GitHub.







