ในโลกของ TypeScript และ JavaScript สมัยใหม่ การเลือก ORM ที่เหมาะสมเป็นเรื่องสำคัญมาก Drizzle ORM เป็นตัวเลือกที่กำลังได้รับความนิยมอย่างรวดเร็วในปี 2026 เพราะมันเบา เร็ว และที่สำคัญคือ Type-Safe อย่างแท้จริง ไม่ต้องมี Code Generation ที่ยุ่งยากแบบ Prisma อีกต่อไป
บทความนี้จะพาคุณเรียนรู้ Drizzle ORM ตั้งแต่แนวคิดพื้นฐานไปจนถึงการใช้งานจริงกับ Framework ยอดนิยม พร้อมเปรียบเทียบกับ ORM ตัวอื่นอย่างละเอียด เพื่อให้คุณตัดสินใจได้ว่า Drizzle เหมาะกับโปรเจกต์ของคุณหรือไม่
Drizzle ORM คืออะไร?
Drizzle ORM คือ TypeScript ORM ที่ออกแบบมาให้มีลักษณะคล้าย SQL มากที่สุด แนวคิดหลักของ Drizzle คือ ถ้าคุณรู้จัก SQL คุณก็รู้จัก Drizzle โดยไม่ต้องเรียนรู้ API ใหม่ทั้งหมดเหมือน ORM ตัวอื่น Drizzle ถูกสร้างขึ้นด้วยปรัชญาว่า ORM ไม่ควรเป็นตัวกั้นระหว่าง Developer กับ Database
จุดเด่นของ Drizzle ที่แตกต่างจาก ORM ทั่วไปคือ:
- Type-Safe แบบ 100% — ทุก Query ถูก Type Check ตั้งแต่ตอน Compile ไม่มี Runtime Error จาก Type ผิด
- ไม่ต้อง Code Generation — ต่างจาก Prisma ที่ต้อง run
prisma generateทุกครั้ง Drizzle ทำงานกับ TypeScript type system โดยตรง - SQL-like Syntax — ถ้าคุณเขียน SQL เป็น คุณเขียน Drizzle ได้ทันที
- Zero Dependencies — ไม่พึ่งพา Runtime dependency ภายนอก ทำให้ Bundle Size เล็กมาก
- Serverless Ready — ออกแบบมาให้ทำงานได้ดีกับ Edge Runtime และ Serverless Environment
ปรัชญาของ Drizzle: If you know SQL, you know Drizzle
Drizzle ยึดหลักว่า SQL เป็นภาษาที่ทรงพลังอยู่แล้ว ไม่ควรซ่อนมันไว้หลัง Abstraction Layer ที่หนาเกินไป ORM หลายตัวพยายามสร้าง API ของตัวเองที่ไม่เหมือน SQL เลย ทำให้ Developer ต้องเรียนรู้ทั้ง SQL และ ORM API แยกกัน Drizzle แก้ปัญหานี้ด้วยการทำให้ API ของมันคล้ายกับ SQL มากที่สุด
ตัวอย่างเช่น ถ้าคุณเขียน SQL ว่า SELECT * FROM users WHERE age > 18 ORDER BY name ใน Drizzle จะเขียนเป็น db.select().from(users).where(gt(users.age, 18)).orderBy(users.name) ซึ่งอ่านแล้วเข้าใจทันทีว่ามันทำอะไร
นอกจากนี้ Drizzle ยังรองรับ Raw SQL ได้ทุกที่ผ่าน sql template literal ทำให้คุณไม่มีทางติดขัดเพราะ ORM ไม่รองรับ Query ที่ซับซ้อน สิ่งนี้เป็นข้อจำกัดที่พบบ่อยใน ORM อื่นๆ
การติดตั้ง Drizzle ORM
# ติดตั้ง Drizzle ORM core
npm install drizzle-orm
# ติดตั้ง Driver สำหรับ Database ที่ใช้
# PostgreSQL
npm install drizzle-orm postgres
npm install -D drizzle-kit
# MySQL
npm install drizzle-orm mysql2
npm install -D drizzle-kit
# SQLite
npm install drizzle-orm better-sqlite3
npm install -D drizzle-kit @types/better-sqlite3
# Turso (LibSQL)
npm install drizzle-orm @libsql/client
npm install -D drizzle-kit
# Neon Serverless
npm install drizzle-orm @neondatabase/serverless
npm install -D drizzle-kit
Schema Definition — การกำหนดโครงสร้างตาราง
Drizzle ใช้ TypeScript ในการกำหนด Schema แทนที่จะใช้ไฟล์ DSL แยกต่างหากเหมือน Prisma Schema ข้อดีคือคุณได้ Type Safety ตั้งแต่ตอน Define Schema เลย และสามารถใช้ TypeScript features ทั้งหมดได้
PostgreSQL Schema
import { pgTable, serial, text, varchar, integer,
boolean, timestamp, pgEnum } from 'drizzle-orm/pg-core';
// กำหนด Enum
export const roleEnum = pgEnum('role', ['admin', 'user', 'moderator']);
// ตาราง Users
export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: text('name').notNull(),
email: varchar('email', { length: 255 }).notNull().unique(),
role: roleEnum('role').default('user'),
age: integer('age'),
isActive: boolean('is_active').default(true),
createdAt: timestamp('created_at').defaultNow(),
updatedAt: timestamp('updated_at').defaultNow(),
});
// ตาราง Posts
export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: text('title').notNull(),
content: text('content'),
authorId: integer('author_id').references(() => users.id),
published: boolean('published').default(false),
createdAt: timestamp('created_at').defaultNow(),
});
// ตาราง Comments
export const comments = pgTable('comments', {
id: serial('id').primaryKey(),
text: text('text').notNull(),
postId: integer('post_id').references(() => posts.id),
userId: integer('user_id').references(() => users.id),
createdAt: timestamp('created_at').defaultNow(),
});
MySQL Schema
import { mysqlTable, serial, text, varchar,
int, boolean, timestamp } from 'drizzle-orm/mysql-core';
export const users = mysqlTable('users', {
id: serial('id').primaryKey(),
name: text('name').notNull(),
email: varchar('email', { length: 255 }).notNull().unique(),
age: int('age'),
createdAt: timestamp('created_at').defaultNow(),
});
SQLite Schema
import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core';
export const users = sqliteTable('users', {
id: integer('id').primaryKey({ autoIncrement: true }),
name: text('name').notNull(),
email: text('email').notNull().unique(),
age: integer('age'),
});
Relations — การกำหนดความสัมพันธ์
Drizzle แยกการกำหนด Relations ออกจาก Schema เพื่อให้ Schema ตรงกับ Database จริงๆ ในขณะที่ Relations เป็น Application-level concept สำหรับใช้กับ Relational Query API
import { relations } from 'drizzle-orm';
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
comments: many(comments),
}));
export const postsRelations = relations(posts, ({ one, many }) => ({
author: one(users, {
fields: [posts.authorId],
references: [users.id],
}),
comments: many(comments),
}));
export const commentsRelations = relations(comments, ({ one }) => ({
post: one(posts, {
fields: [comments.postId],
references: [posts.id],
}),
user: one(users, {
fields: [comments.userId],
references: [users.id],
}),
}));
Query Builder — การ Query ข้อมูล
การเชื่อมต่อ Database
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema';
const client = postgres(process.env.DATABASE_URL!);
const db = drizzle(client, { schema });
SELECT — ดึงข้อมูล
// SELECT * FROM users
const allUsers = await db.select().from(users);
// SELECT ด้วย WHERE
import { eq, gt, like, and, or, ne, between, inArray } from 'drizzle-orm';
// WHERE age > 18
const adults = await db.select().from(users).where(gt(users.age, 18));
// WHERE email LIKE '%@gmail.com'
const gmailUsers = await db.select().from(users)
.where(like(users.email, '%@gmail.com'));
// WHERE age > 18 AND isActive = true
const activeAdults = await db.select().from(users)
.where(and(gt(users.age, 18), eq(users.isActive, true)));
// WHERE role IN ('admin', 'moderator')
const staff = await db.select().from(users)
.where(inArray(users.role, ['admin', 'moderator']));
// SELECT เฉพาะบาง Column
const userNames = await db.select({
id: users.id,
name: users.name,
}).from(users);
// ORDER BY, LIMIT, OFFSET
const paged = await db.select().from(users)
.orderBy(users.name)
.limit(10)
.offset(20);
INSERT — เพิ่มข้อมูล
// INSERT เดี่ยว
await db.insert(users).values({
name: 'สมชาย',
email: 'somchai@example.com',
age: 25,
});
// INSERT หลายรายการ
await db.insert(users).values([
{ name: 'สมชาย', email: 'somchai@example.com', age: 25 },
{ name: 'สมหญิง', email: 'somying@example.com', age: 30 },
]);
// INSERT ... RETURNING (PostgreSQL)
const newUser = await db.insert(users).values({
name: 'สมศรี',
email: 'somsri@example.com',
}).returning();
// INSERT ... ON CONFLICT (Upsert)
await db.insert(users).values({
name: 'สมชาย',
email: 'somchai@example.com',
}).onConflictDoUpdate({
target: users.email,
set: { name: 'สมชาย (Updated)' },
});
UPDATE — แก้ไขข้อมูล
// UPDATE users SET name = 'ชื่อใหม่' WHERE id = 1
await db.update(users)
.set({ name: 'ชื่อใหม่' })
.where(eq(users.id, 1));
// UPDATE พร้อม RETURNING
const updated = await db.update(users)
.set({ isActive: false })
.where(lt(users.age, 18))
.returning();
DELETE — ลบข้อมูล
// DELETE FROM users WHERE id = 1
await db.delete(users).where(eq(users.id, 1));
// DELETE พร้อม RETURNING
const deleted = await db.delete(users)
.where(eq(users.isActive, false))
.returning();
Joins — การ Join ตาราง
// INNER JOIN
const postsWithAuthors = await db.select({
postTitle: posts.title,
authorName: users.name,
}).from(posts)
.innerJoin(users, eq(posts.authorId, users.id));
// LEFT JOIN
const usersWithPosts = await db.select({
userName: users.name,
postTitle: posts.title,
}).from(users)
.leftJoin(posts, eq(users.id, posts.authorId));
// Multiple JOINs
const commentsWithDetails = await db.select({
comment: comments.text,
postTitle: posts.title,
userName: users.name,
}).from(comments)
.innerJoin(posts, eq(comments.postId, posts.id))
.innerJoin(users, eq(comments.userId, users.id));
Aggregations และ Group By
import { count, avg, sum, max, min } from 'drizzle-orm';
// COUNT
const userCount = await db.select({
total: count(),
}).from(users);
// GROUP BY พร้อม COUNT
const postsByAuthor = await db.select({
authorId: posts.authorId,
postCount: count(),
}).from(posts)
.groupBy(posts.authorId);
// HAVING
const activeAuthors = await db.select({
authorId: posts.authorId,
postCount: count(),
}).from(posts)
.groupBy(posts.authorId)
.having(gt(count(), 5));
// AVG, SUM
const ageStats = await db.select({
avgAge: avg(users.age),
totalAge: sum(users.age),
maxAge: max(users.age),
minAge: min(users.age),
}).from(users);
Subqueries
// Subquery ใน WHERE
const subquery = db.select({ id: users.id }).from(users)
.where(eq(users.role, 'admin'));
const adminPosts = await db.select().from(posts)
.where(inArray(posts.authorId, subquery));
// Subquery เป็น Derived Table
const sq = db.select({
authorId: posts.authorId,
postCount: count().as('post_count'),
}).from(posts)
.groupBy(posts.authorId)
.as('post_counts');
const usersWithPostCount = await db.select({
name: users.name,
postCount: sq.postCount,
}).from(users)
.leftJoin(sq, eq(users.id, sq.authorId));
Prepared Statements
Drizzle รองรับ Prepared Statements เพื่อเพิ่มประสิทธิภาพ Query ที่ถูกเรียกซ้ำบ่อยๆ และป้องกัน SQL Injection ได้อย่างสมบูรณ์
import { placeholder } from 'drizzle-orm';
// สร้าง Prepared Statement
const getUserById = db.select().from(users)
.where(eq(users.id, placeholder('id')))
.prepare('get_user_by_id');
// เรียกใช้ซ้ำได้หลายครั้ง
const user1 = await getUserById.execute({ id: 1 });
const user2 = await getUserById.execute({ id: 2 });
// Prepared Statement กับหลาย Parameters
const getUsersByAgeRange = db.select().from(users)
.where(and(
gt(users.age, placeholder('minAge')),
lt(users.age, placeholder('maxAge'))
))
.prepare('get_users_by_age_range');
const youngUsers = await getUsersByAgeRange.execute({ minAge: 18, maxAge: 25 });
Relational Queries — Query แบบ Nested
นอกจาก SQL-like Query Builder แล้ว Drizzle ยังมี Relational Query API ที่ช่วยให้ดึงข้อมูลแบบ Nested ได้ง่ายขึ้น คล้ายกับ Prisma include แต่ยังคง Type-Safe เหมือนเดิม
// ดึง Users พร้อม Posts ทั้งหมด
const usersWithPosts = await db.query.users.findMany({
with: {
posts: true,
},
});
// ดึง Posts พร้อม Author และ Comments
const postsWithDetails = await db.query.posts.findMany({
with: {
author: true,
comments: {
with: {
user: true,
},
},
},
where: eq(posts.published, true),
orderBy: [desc(posts.createdAt)],
limit: 10,
});
// เลือกเฉพาะบาง Column
const slimPosts = await db.query.posts.findMany({
columns: {
id: true,
title: true,
},
with: {
author: {
columns: {
name: true,
},
},
},
});
// findFirst
const firstAdmin = await db.query.users.findFirst({
where: eq(users.role, 'admin'),
});
Drizzle Kit — Migrations และ Schema Management
Drizzle Kit เป็นเครื่องมือ CLI ที่ช่วยจัดการ Database Migrations มันจะอ่าน Schema ของคุณแล้วสร้าง SQL Migration Files ให้อัตโนมัติ
Configuration
// drizzle.config.ts
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
schema: './src/db/schema.ts',
out: './drizzle',
dialect: 'postgresql',
dbCredentials: {
url: process.env.DATABASE_URL!,
},
});
คำสั่ง Drizzle Kit
# สร้าง Migration จาก Schema ที่เปลี่ยนแปลง
npx drizzle-kit generate
# ดู SQL ที่จะถูก Run
npx drizzle-kit migrate
# Push Schema ตรงไป Database (Development)
npx drizzle-kit push
# ดึง Schema จาก Database ที่มีอยู่
npx drizzle-kit introspect
# ตรวจสอบว่า Schema ตรงกับ Database หรือไม่
npx drizzle-kit check
# เปิด Drizzle Studio
npx drizzle-kit studio
push สำหรับ Development ที่ต้องการเปลี่ยน Schema บ่อยๆ ใช้ generate สำหรับ Production ที่ต้องการ Migration Files เพื่อ Track Changes
Drizzle-Zod — Validation จาก Schema
Drizzle สามารถสร้าง Zod Schema จาก Database Schema ได้อัตโนมัติ ทำให้คุณไม่ต้องเขียน Validation Schema ซ้ำซ้อน เป็น Single Source of Truth จริงๆ
npm install drizzle-zod
import { createInsertSchema, createSelectSchema } from 'drizzle-zod';
import { z } from 'zod';
// สร้าง Zod Schema อัตโนมัติ
const insertUserSchema = createInsertSchema(users);
const selectUserSchema = createSelectSchema(users);
// Customize Validation
const insertUserSchemaCustom = createInsertSchema(users, {
email: (schema) => schema.email('กรุณากรอก Email ที่ถูกต้อง'),
name: (schema) => schema.min(2, 'ชื่อต้องมีอย่างน้อย 2 ตัวอักษร'),
age: (schema) => schema.min(1).max(150),
});
// ใช้กับ API Route
app.post('/users', async (req, res) => {
const result = insertUserSchemaCustom.safeParse(req.body);
if (!result.success) {
return res.status(400).json(result.error);
}
const user = await db.insert(users).values(result.data).returning();
res.json(user);
});
Drizzle Studio
Drizzle Studio เป็น GUI สำหรับจัดการ Database ที่มาพร้อมกับ Drizzle Kit ใช้ง่าย ดูข้อมูล แก้ไขข้อมูล และ Run Query ได้ผ่าน Browser โดยไม่ต้องติดตั้งอะไรเพิ่ม
# เปิด Drizzle Studio
npx drizzle-kit studio
# จะเปิด Browser ที่ https://local.drizzle.studio
Drizzle Studio รองรับการดูโครงสร้างตาราง การ Browse ข้อมูล การแก้ไขข้อมูลแบบ Inline การ Filter และ Sort รวมถึงการ Export ข้อมูลเป็น CSV ซึ่งสะดวกมากสำหรับการ Debug และจัดการข้อมูลระหว่างการพัฒนา
Drizzle กับ Framework ยอดนิยม
Next.js
// src/db/index.ts
import { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';
import * as schema from './schema';
const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle(sql, { schema });
// app/api/users/route.ts
import { db } from '@/db';
import { users } from '@/db/schema';
export async function GET() {
const allUsers = await db.query.users.findMany();
return Response.json(allUsers);
}
Hono
import { Hono } from 'hono';
import { drizzle } from 'drizzle-orm/d1';
import * as schema from './schema';
const app = new Hono<{ Bindings: { DB: D1Database } }>()
app.get('/users', async (c) => {
const db = drizzle(c.env.DB, { schema });
const users = await db.query.users.findMany();
return c.json(users);
});
Nuxt
// server/utils/db.ts
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from '../db/schema';
const client = postgres(process.env.DATABASE_URL!);
export const db = drizzle(client, { schema });
// server/api/users.get.ts
export default defineEventHandler(async () => {
return await db.query.users.findMany();
});
SvelteKit
// src/lib/server/db.ts
import { drizzle } from 'drizzle-orm/postgres-js';
import postgres from 'postgres';
import * as schema from './schema';
const client = postgres(process.env.DATABASE_URL!);
export const db = drizzle(client, { schema });
// src/routes/users/+page.server.ts
import { db } from '$lib/server/db';
import { users } from '$lib/server/schema';
export async function load() {
const allUsers = await db.query.users.findMany();
return { users: allUsers };
}
Database Support — ฐานข้อมูลที่รองรับ
Drizzle รองรับฐานข้อมูลหลากหลายตัว ทั้ง Traditional Database และ Serverless Database ซึ่งเป็นจุดแข็งที่สำคัญ:
| Database | Driver | ใช้กับ |
|---|---|---|
| PostgreSQL | postgres, node-postgres, Neon | Production ทั่วไป |
| MySQL | mysql2, PlanetScale | Production ทั่วไป |
| SQLite | better-sqlite3, Bun SQLite | Local Development, Embedded |
| Cloudflare D1 | D1 Driver | Cloudflare Workers |
| Turso (LibSQL) | @libsql/client | Edge, Embedded Replicas |
| Neon | @neondatabase/serverless | Serverless PostgreSQL |
| PlanetScale | @planetscale/database | Serverless MySQL |
| Vercel Postgres | @vercel/postgres | Vercel Platform |
| Supabase | postgres | Supabase Platform |
Performance Benchmarks — Drizzle vs Prisma
ในการทดสอบประสิทธิภาพที่ทำในปี 2026 Drizzle แสดงให้เห็นว่ามีความเร็วที่เหนือกว่า Prisma อย่างชัดเจนในหลายด้าน โดยเฉพาะเรื่อง Cold Start และ Bundle Size ซึ่งสำคัญมากสำหรับ Serverless
| Metric | Drizzle ORM | Prisma |
|---|---|---|
| Bundle Size | ~60 KB | ~2.5 MB+ (Engine) |
| Cold Start | < 10ms | ~200-500ms |
| Simple SELECT | ~0.3ms | ~1.2ms |
| JOIN Query | ~0.8ms | ~3.5ms |
| Code Generation | ไม่ต้อง | ต้อง run generate |
| Memory Usage | ต่ำมาก | สูง (Rust Engine) |
Drizzle vs Prisma vs TypeORM — เปรียบเทียบรอบด้าน
| Feature | Drizzle | Prisma | TypeORM |
|---|---|---|---|
| Type Safety | 100% (Compile-time) | ดี (Generated Types) | ปานกลาง |
| Learning Curve | ต่ำ (ถ้ารู้ SQL) | ปานกลาง | สูง |
| SQL-like API | มาก | น้อย (Custom API) | ปานกลาง |
| Code Generation | ไม่ต้อง | ต้อง | ไม่ต้อง |
| Bundle Size | เล็กมาก | ใหญ่ | ปานกลาง |
| Serverless | ดีเยี่ยม | ปานกลาง | ไม่ค่อยเหมาะ |
| Raw SQL | ดีเยี่ยม | จำกัด | ดี |
| Migration | Drizzle Kit | Prisma Migrate | Built-in |
| GUI Tool | Drizzle Studio | Prisma Studio | ไม่มี |
| Community | กำลังโต | ใหญ่ | ใหญ่ |
| Edge Runtime | รองรับ | จำกัด | ไม่รองรับ |
Batch Operations
Drizzle รองรับการทำ Batch Operations เพื่อส่งหลาย Query ไปยัง Database ในรอบเดียว ลด Round-trip และเพิ่มประสิทธิภาพ
// Batch Insert
await db.insert(users).values([
{ name: 'User 1', email: 'user1@example.com' },
{ name: 'User 2', email: 'user2@example.com' },
{ name: 'User 3', email: 'user3@example.com' },
// ... สามารถใส่ได้หลายพันรายการ
]);
// Transaction
await db.transaction(async (tx) => {
const newUser = await tx.insert(users).values({
name: 'สมชาย',
email: 'somchai@example.com',
}).returning();
await tx.insert(posts).values({
title: 'บทความแรก',
authorId: newUser[0].id,
});
});
// Batch Queries (ส่งหลาย Query พร้อมกัน)
const [allUsers, allPosts, userCount] = await db.batch([
db.select().from(users),
db.select().from(posts),
db.select({ count: count() }).from(users),
]);
Custom Types
Drizzle ให้คุณสร้าง Custom Column Types ได้ เพื่อจัดการกับ Data Types ที่ไม่ได้มีอยู่ใน Built-in Types เช่น JSON, Array หรือ Custom Formats
import { customType } from 'drizzle-orm/pg-core';
// Custom JSON Type ที่ Type-Safe
const jsonb = () => customType<{ data: T; driverData: string }>({
dataType() {
return 'jsonb';
},
toDriver(value: T): string {
return JSON.stringify(value);
},
fromDriver(value: string): T {
return JSON.parse(value) as T;
},
});
// ใช้งาน
interface UserPreferences {
theme: 'light' | 'dark';
language: string;
notifications: boolean;
}
export const userSettings = pgTable('user_settings', {
id: serial('id').primaryKey(),
userId: integer('user_id').references(() => users.id),
preferences: jsonb()('preferences').notNull(),
});
เมื่อไหร่ควรเลือก Drizzle เมื่อไหร่ควรเลือก Prisma?
เลือก Drizzle เมื่อ:
- คุณเชี่ยวชาญ SQL และต้องการ ORM ที่ไม่ซ่อน SQL ไว้
- โปรเจกต์ Deploy บน Serverless หรือ Edge Runtime
- ต้องการ Bundle Size เล็กและ Cold Start เร็ว
- ต้องการ Type Safety แบบ 100% โดยไม่ต้อง Code Generation
- ใช้ Database หลายตัวหรือ Database ที่หลากหลาย เช่น D1 หรือ Turso
- ต้องการเขียน Complex Query ที่ ORM ทั่วไปทำไม่ได้
เลือก Prisma เมื่อ:
- ทีมไม่ค่อยเชี่ยวชาญ SQL และต้องการ Abstraction ที่สูงกว่า
- ต้องการ Ecosystem ที่สมบูรณ์กว่า เช่น Prisma Pulse และ Prisma Accelerate
- ต้องการ Documentation ที่ละเอียดและ Community ที่ใหญ่กว่า
- โปรเจกต์ไม่ได้ Deploy บน Serverless และ Cold Start ไม่ใช่ปัญหา
- ต้องการ Schema-first Approach ที่ชัดเจน
Best Practices สำหรับ Drizzle ORM
- แยก Schema Files: อย่ารวม Schema ทั้งหมดไว้ในไฟล์เดียว แยกตาม Domain เช่น
users.ts,posts.ts,orders.ts - ใช้ Prepared Statements: สำหรับ Query ที่เรียกบ่อยๆ เพื่อเพิ่มประสิทธิภาพและความปลอดภัย
- ใช้ Transaction: สำหรับ Operations ที่ต้องทำพร้อมกัน เพื่อรักษา Data Integrity
- ใช้ Drizzle-Zod: สร้าง Validation Schema อัตโนมัติแทนการเขียนมือเพื่อลด Duplication
- ใช้ generate สำหรับ Production: อย่าใช้ push ใน Production เพราะมันจะเปลี่ยน Schema โดยไม่มี Migration File ให้ Track
- Index สำคัญ: อย่าลืมกำหนด Index สำหรับ Column ที่ Query บ่อยๆ
import { index, uniqueIndex } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: serial('id').primaryKey(),
email: varchar('email', { length: 255 }).notNull(),
name: text('name'),
createdAt: timestamp('created_at').defaultNow(),
}, (table) => ({
emailIdx: uniqueIndex('email_idx').on(table.email),
nameIdx: index('name_idx').on(table.name),
}));
สรุป
Drizzle ORM เป็นทางเลือกที่ยอดเยี่ยมสำหรับ TypeScript Developer ที่ต้องการ ORM ที่เบา เร็ว Type-Safe และไม่ซ่อน SQL ไว้หลัง Abstraction ที่ซับซ้อน ด้วยปรัชญา If you know SQL you know Drizzle ทำให้การเรียนรู้เป็นเรื่องง่ายสำหรับ Developer ที่มีพื้นฐาน SQL อยู่แล้ว
ในปี 2026 Drizzle กำลังเติบโตอย่างรวดเร็วและกลายเป็นตัวเลือกอันดับต้นๆ สำหรับ Serverless และ Edge Computing ถ้าคุณกำลังเริ่มโปรเจกต์ใหม่ด้วย TypeScript ลอง Drizzle ดูสักครั้ง คุณอาจไม่อยากกลับไปใช้ ORM ตัวอื่นอีกเลย เพราะมันทำให้การทำงานกับ Database เป็นเรื่องสนุกและปลอดภัยไปพร้อมกัน
