주요 변경 사항
중첩 관계를 통한 필터링 지원 제거
다음 예제는 0.28.0에서 작동하지 않습니다:
const usersWithPosts = await db.query.users.findMany({
where: (table, { sql }) => (sql`json_array_length(${table.posts}) > 0`),
with: {
posts: true,
},
});where 콜백의 table 객체는 더 이상 with 및 extras의 필드를 포함하지 않습니다. 더 효율적인 관계형 쿼리를 구축하기 위해 이를 제거했으며, 이를 통해 행 읽기 및 성능이 향상되었습니다.
이전에 where 콜백에서 해당 필드를 사용했다면, 다음과 같은 해결 방법이 있습니다:
- 행을 조회한 후 코드 레벨에서 수동으로 필터 적용
- Core API 사용
mysql2 드라이버의 Relational Queries mode 설정 추가
Drizzle 관계형 쿼리는 항상 데이터베이스에서 실행할 정확히 하나의 SQL 문을 생성하며, 특정 주의사항이 있습니다. 모든 데이터베이스를 최상의 수준으로 지원하기 위해 모드를 도입했습니다.
Drizzle 관계형 쿼리는 내부적으로 서브쿼리의 lateral join을 사용하는데, 현재 PlanetScale은 이를 지원하지 않습니다.
일반 MySQL 데이터베이스와 mysql2 드라이버를 사용하는 경우 - mode: "default"를 지정해야 합니다.
PlanetScale과 mysql2 드라이버를 사용하는 경우 - mode: "planetscale"을 지정해야 합니다.
import { drizzle } from 'drizzle-orm/mysql2';
import mysql from 'mysql2/promise';
import * as schema from './schema';
const client = await mysql.createConnection({
uri: process.env.PLANETSCALE_DATABASE_URL,
});
const db = drizzle({ client, schema, mode: 'planetscale' });대규모 스키마의 IntelliSense 성능 향상
85개의 테이블, 666개의 컬럼, 26개의 enum, 172개의 인덱스, 133개의 외래 키를 가진 데이터베이스 스키마로 진단을 수행했습니다. 내부 타입을 최적화하여 IntelliSense에서 430% 속도 향상을 달성했습니다.
Relational Queries 성능 및 읽기 사용량 개선
이번 릴리스에서는 Relational Query API의 쿼리 생성 방식을 완전히 변경했습니다.
쿼리 생성 전략의 주요 변경 사항은 다음과 같습니다:
-
Lateral Join: 새 버전에서는 “LEFT JOIN LATERAL” 절을 사용하여 관련 테이블에서 특정 데이터를 효율적으로 조회합니다. PlanetScale의 MySQL과 SQLite의 경우 단순 서브쿼리 조회를 사용하여 쿼리 계획과 전체 성능을 개선했습니다.
-
선택적 데이터 조회: 새 버전에서는 테이블에서 필요한 데이터만 조회합니다. 이러한 타겟 데이터 조회는 불필요한 정보 가져오기를 줄여 처리할 데이터셋을 줄이고 실행 속도를 높입니다.
-
집계 감소: 새 버전에서는 집계 함수(예: COUNT, json_agg)의 수를 줄였습니다. lateral join 내에서 json_build_array를 직접 사용함으로써 Drizzle은 더 간소화된 방식으로 데이터를 집계하여 쿼리 성능을 향상시킵니다.
-
그룹화 단순화: 새 버전에서는 lateral join과 서브쿼리가 이미 데이터 집계를 더 효율적으로 처리하므로 GROUP BY 절이 제거되었습니다.
다음 Drizzle 쿼리의 경우
const items = await db.query.comments.findMany({
limit,
orderBy: comments.id,
with: {
user: {
columns: { name: true },
},
post: {
columns: { title: true },
with: {
user: {
columns: { name: true },
},
},
},
},
});-- 현재 생성되는 쿼리
select "comments"."id",
"comments"."user_id",
"comments"."post_id",
"comments"."content",
"comments_user"."data" as "user",
"comments_post"."data" as "post"
from "comments"
left join lateral (select json_build_array("comments_user"."name") as "data"
from (select *
from "users" "comments_user"
where "comments_user"."id" = "comments"."user_id"
limit 1) "comments_user") "comments_user" on true
left join lateral (select json_build_array("comments_post"."title", "comments_post_user"."data") as "data"
from (select *
from "posts" "comments_post"
where "comments_post"."id" = "comments"."post_id"
limit 1) "comments_post"
left join lateral (select json_build_array("comments_post_user"."name") as "data"
from (select *
from "users" "comments_post_user"
where "comments_post_user"."id" = "comments_post"."user_id"
limit 1) "comments_post_user") "comments_post_user"
on true) "comments_post" on true
order by "comments"."id"
limit 1-- 이전에 생성되던 쿼리
SELECT "id",
"user_id",
"post_id",
"content",
"user"::JSON,
"post"::JSON
FROM
(SELECT "comments".*,
CASE
WHEN count("comments_post"."id") = 0 THEN '[]'
ELSE json_agg(json_build_array("comments_post"."title", "comments_post"."user"::JSON))::text
END AS "post"
FROM
(SELECT "comments".*,
CASE
WHEN count("comments_user"."id") = 0 THEN '[]'
ELSE json_agg(json_build_array("comments_user"."name"))::text
END AS "user"
FROM "comments"
LEFT JOIN
(SELECT "comments_user".*
FROM "users" "comments_user") "comments_user" ON "comments"."user_id" = "comments_user"."id"
GROUP BY "comments"."id",
"comments"."user_id",
"comments"."post_id",
"comments"."content") "comments"
LEFT JOIN
(SELECT "comments_post".*
FROM
(SELECT "comments_post".*,
CASE
WHEN count("comments_post_user"."id") = 0 THEN '[]'
ELSE json_agg(json_build_array("comments_post_user"."name"))
END AS "user"
FROM "posts" "comments_post"
LEFT JOIN
(SELECT "comments_post_user".*
FROM "users" "comments_post_user") "comments_post_user" ON "comments_post"."user_id" = "comments_post_user"."id"
GROUP BY "comments_post"."id") "comments_post") "comments_post" ON "comments"."post_id" = "comments_post"."id"
GROUP BY "comments"."id",
"comments"."user_id",
"comments"."post_id",
"comments"."content",
"comments"."user") "comments"
LIMIT 1문서에서 Relational Queries에 대해 자세히 알아보세요.
모든 컬럼에 기본값을 사용하는 행 삽입 기능
이제 빈 객체 또는 빈 객체 배열을 제공할 수 있으며, Drizzle이 모든 기본값을 데이터베이스에 삽입합니다.
// 모든 기본값으로 1개 행 삽입
await db.insert(usersTable).values({});
// 모든 기본값으로 2개 행 삽입
await db.insert(usersTable).values([{}, {}]);