From 3fa50e79f12fe2b66ebd5d643ed597c6a121b198 Mon Sep 17 00:00:00 2001 From: muqiuhan Date: Sat, 3 May 2025 10:47:05 +0000 Subject: deploy: a0dad147ccf1d831c5f48d8d0e868160a23cc92c --- search.xml | 319 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 179 insertions(+), 140 deletions(-) (limited to 'search.xml') diff --git a/search.xml b/search.xml index 0c352b3d..a8b0c1b5 100644 --- a/search.xml +++ b/search.xml @@ -845,7 +845,7 @@

Prisma ORM 在设计上就考虑了 N+1 问题,并提供了一种既方便开发者又高效的解决方案。当使用 Prisma Client 查询数据并需要包含关联模型时,Prisma 会自动优化查询,避免产生 N+1 查询,主要通过关系查询(Relation Queries)中的 include 选项或嵌套读取(nested reads)来实现这一点:

假设想获取所有用户及其发布的帖子,使用 Prisma Client,可以这样写:

-
import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function getUsersWithPosts() {
const usersWithPosts = await prisma.user.findMany({
include: {
posts: true, // 指示 Prisma 加载关联的 posts
},
})
// usersWithPosts 包含了用户列表,每个用户对象中都有一个 posts 数组
console.log(usersWithPosts)
}

getUsersWithPosts()
.catch((e) => {
throw e
})
.finally(async () => {
await prisma.$disconnect()
})
+
import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function getUsersWithPosts() {
const usersWithPosts = await prisma.user.findMany({
include: {
posts: true, // 指示 Prisma 加载关联的 posts
},
})
// usersWithPosts 包含了用户列表,每个用户对象中都有一个 posts 数组
console.log(usersWithPosts)
}

getUsersWithPosts()
.catch((e) => {
throw e
})
.finally(async () => {
await prisma.$disconnect()
})

当执行上述查询时,Prisma 不会 生成 N+1 个 SQL 查询。而是首先会分析请求,并将其转化为数量非常有限的高效 SQL 查询。对于上面这个一对多关系的 include 查询,Prisma 通常会执行以下两步(类似于批量加载策略):

    @@ -1133,67 +1133,6 @@
  1. [ANN] Docfd: TUI multiline fuzzy document finder 2.2.0

  2. -]]> - - Technique - - - - OCaml News 2024-5 - /2024/06/27/OCaml-News-2024-5/ - 语言的发展 -

    新消息

    -

    有价值的文章

    -

    有趣的项目

    ]]>
    Technique @@ -1313,6 +1252,67 @@
  3. llama: A library for building software-defined modular synthesizers in a declarative style.

  4. +]]> + + Technique + +
    + + OCaml News 2024-5 + /2024/06/27/OCaml-News-2024-5/ + 语言的发展 +

    新消息

    +

    有价值的文章

    +

    有趣的项目

    ]]>
    Technique @@ -1618,7 +1618,7 @@

    一对一的 self-relation 需要两个端点,即使这两个端点是同一条数据。

    而在关系型数据库中,一对一的 self-relation 可以用如下 SQL 描述:

    -
    CREATE TABLE "User" (
    id SERIAL PRIMARY KEY,
    "name" TEXT,
    "successorId" INTEGER
    );

    ALTER TABLE "User" ADD CONSTRAINT fk_successor_user FOREIGN KEY ("successorId") REFERENCES "User" (id);

    ALTER TABLE "User" ADD CONSTRAINT successor_unique UNIQUE ("successorId");
    +
    CREATE TABLE "User" (
    id SERIAL PRIMARY KEY,
    "name" TEXT,
    "successorId" INTEGER
    );

    ALTER TABLE "User" ADD CONSTRAINT fk_successor_user FOREIGN KEY ("successorId") REFERENCES "User" (id);

    ALTER TABLE "User" ADD CONSTRAINT successor_unique UNIQUE ("successorId");

    一对多

    model User {
    id Int @id @default(autoincrement())
    name String?
    teacherId Int?
    teacher User? @relation("TeacherStudents", fields: [teacherId], references: [id])
    students User[] @relation("TeacherStudents")
    }
    @@ -1631,7 +1631,7 @@

    可以通过将 teacher 字段设为 required 来要求每个 User 都有一名 teacher。

    用 SQL 描述 User model:

    -
    CREATE TABLE "User" (
    id SERIAL PRIMARY KEY,
    "name" TEXT,
    "teacherId" INTEGER
    );

    ALTER TABLE "User" ADD CONSTRAINT fk_teacherid_user FOREIGN KEY ("teacherId") REFERENCES "User" (id);
    +
    CREATE TABLE "User" (
    id SERIAL PRIMARY KEY,
    "name" TEXT,
    "teacherId" INTEGER
    );

    ALTER TABLE "User" ADD CONSTRAINT fk_teacherid_user FOREIGN KEY ("teacherId") REFERENCES "User" (id);

    teacherId 没有使用 UNIQUE 约束,这代表着多个 students 可以有同一个 teacher

    多对多

    model User {
    id Int @id @default(autoincrement())
    name String?
    followedBy User[] @relation("UserFollows")
    following User[] @relation("UserFollows")
    }
    @@ -1648,7 +1648,7 @@
    model User {
    id Int @id @default(autoincrement())
    name String?
    followedBy Follows[] @relation("followedBy")
    following Follows[] @relation("following")
    }

    model Follows {
    followedBy User @relation("followedBy", fields: [followedById], references: [id])
    followedById Int
    following User @relation("following", fields: [followingId], references: [id])
    followingId Int

    @@id([followingId, followedById])
    }

    在关系型数据库中,可以用如下 SQL 描述:

    -
    CREATE TABLE "User" (
    id integer DEFAULT nextval('"User_id_seq"'::regclass) PRIMARY KEY,
    name text
    );
    CREATE TABLE "_UserFollows" (
    "A" integer NOT NULL REFERENCES "User"(id) ON DELETE CASCADE ON UPDATE CASCADE,
    "B" integer NOT NULL REFERENCES "User"(id) ON DELETE CASCADE ON UPDATE CASCADE
    );
    +
    CREATE TABLE "User" (
    id integer DEFAULT nextval('"User_id_seq"'::regclass) PRIMARY KEY,
    name text
    );
    CREATE TABLE "_UserFollows" (
    "A" integer NOT NULL REFERENCES "User"(id) ON DELETE CASCADE ON UPDATE CASCADE,
    "B" integer NOT NULL REFERENCES "User"(id) ON DELETE CASCADE ON UPDATE CASCADE
    );

    在同一模型上建立多个 self-relations

    model User {
    id Int @id @default(autoincrement())
    name String?
    teacherId Int?
    teacher User? @relation("TeacherStudents", fields: [teacherId], references: [id])
    students User[] @relation("TeacherStudents")
    followedBy User[] @relation("UserFollows")
    following User[] @relation("UserFollows")
    }
    @@ -1713,10 +1713,10 @@
  5. IGenericRepository 中定义的函数是每个 Repository 公开的通用存储函数。
  6. 以上这些就是对业务中的实体的 Repository 抽象,这样就隔离开了业务和存储逻辑,例如使用 MongoDB,可以实现一个 MongoGenericRepository:

    -
    import { Model } from 'mongoose';
    import { IGenericRepository } from '../../../core';

    export class MongoGenericRepository<T> implements IGenericRepository<T> {
    private _repository: Model<T>;
    private _populateOnFind: string[];

    constructor(repository: Model<T>, populateOnFind: string[] = []) {
    this._repository = repository;
    this._populateOnFind = populateOnFind;
    }

    getAll(): Promise<T[]> {
    return this._repository.find().populate(this._populateOnFind).exec();
    }

    get(id: any): Promise<T> {
    return this._repository.findById(id).populate(this._populateOnFind).exec();
    }

    create(item: T): Promise<T> {
    return this._repository.create(item);
    }

    update(id: string, item: T) {
    return this._repository.findByIdAndUpdate(id, item);
    }
    }
    +
    import { Model } from 'mongoose';
    import { IGenericRepository } from '../../../core';

    export class MongoGenericRepository<T> implements IGenericRepository<T> {
    private _repository: Model<T>;
    private _populateOnFind: string[];

    constructor(repository: Model<T>, populateOnFind: string[] = []) {
    this._repository = repository;
    this._populateOnFind = populateOnFind;
    }

    getAll(): Promise<T[]> {
    return this._repository.find().populate(this._populateOnFind).exec();
    }

    get(id: any): Promise<T> {
    return this._repository.findById(id).populate(this._populateOnFind).exec();
    }

    create(item: T): Promise<T> {
    return this._repository.create(item);
    }

    update(id: string, item: T) {
    return this._repository.findByIdAndUpdate(id, item);
    }
    }

    然后实现一个 MongoDataServices:

    -
    import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
    import { InjectModel } from '@nestjs/mongoose';
    import { Model } from 'mongoose';
    import { IDataServices } from '../../../core';
    import { MongoGenericRepository } from './mongo-generic-repository';
    import {
    Author,
    AuthorDocument,
    Book,
    BookDocument,
    Genre,
    GenreDocument,
    } from './model';

    @Injectable()
    export class MongoDataServices
    implements IDataServices, OnApplicationBootstrap
    {
    authors: MongoGenericRepository<Author>;
    books: MongoGenericRepository<Book>;
    genres: MongoGenericRepository<Genre>;

    constructor(
    @InjectModel(Author.name)
    private AuthorRepository: Model<AuthorDocument>,
    @InjectModel(Book.name)
    private BookRepository: Model<BookDocument>,
    @InjectModel(Genre.name)
    private GenreRepository: Model<GenreDocument>,
    ) {}

    onApplicationBootstrap() {
    this.authors = new MongoGenericRepository<Author>(this.AuthorRepository);
    this.books = new MongoGenericRepository<Book>(this.BookRepository, [
    'author',
    'genre',
    ]);
    this.genres = new MongoGenericRepository<Genre>(this.GenreRepository);
    }
    }
    +
    import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
    import { InjectModel } from '@nestjs/mongoose';
    import { Model } from 'mongoose';
    import { IDataServices } from '../../../core';
    import { MongoGenericRepository } from './mongo-generic-repository';
    import {
    Author,
    AuthorDocument,
    Book,
    BookDocument,
    Genre,
    GenreDocument,
    } from './model';

    @Injectable()
    export class MongoDataServices
    implements IDataServices, OnApplicationBootstrap
    {
    authors: MongoGenericRepository<Author>;
    books: MongoGenericRepository<Book>;
    genres: MongoGenericRepository<Genre>;

    constructor(
    @InjectModel(Author.name)
    private AuthorRepository: Model<AuthorDocument>,
    @InjectModel(Book.name)
    private BookRepository: Model<BookDocument>,
    @InjectModel(Genre.name)
    private GenreRepository: Model<GenreDocument>,
    ) {}

    onApplicationBootstrap() {
    this.authors = new MongoGenericRepository<Author>(this.AuthorRepository);
    this.books = new MongoGenericRepository<Book>(this.BookRepository, [
    'author',
    'genre',
    ]);
    this.genres = new MongoGenericRepository<Genre>(this.GenreRepository);
    }
    }

    Sunday, March 30, 2025 7:58 PM:

    @@ -2085,49 +2085,6 @@

TDD 和 DDD 并不冲突,实际上它们可以互补。TDD 可以帮助确保代码的正确性和可靠性,而 DDD 可以确保系统与业务需求紧密结合。在进行 TDD 时,可以使用 DDD 的领域模型和 Ubiquitous Language 来编写测试用例,确保测试覆盖了业务需求。在进行 DDD 时,可以使用 TDD 来驱动实现,确保每个领域模型的实现。

-]]> - - Technique - - - - TypeScript With Rust Errors, No Try Catch, Heresy - /2023/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/ - -

It’s hard to miss things when you don’t know different things exist

- -

The first problem is, and personally, I believe it’s the biggest JavaScript problem ever: we don’t know what can throw an error. From a JavaScript error perspective, it’s the same as the following:

-
try {
let data = “Hello”;
} catch (err) {
console.error(err);
}
- -

JavaScript doesn’t know; JavaScript doesn’t care. You should know.

-

Second thing, this is perfectly viable code:

-
const request = { name: “test”, value: 2n };
const body = JSON.stringify(request);
const response = await fetch("https://example.com", {
method: “POST”,
body,
});
if (!response.ok) {
return;
}
- -

No errors, no linters, even though this can break your app.

-

Right now, in my head, I can hear, “What’s the problem, just use try/catch everywhere.” Here comes the third problem: we don’t know which one is thrown. Of course, we can somehow guess by the error message, but what about bigger services/functions with many places where errors can happen? Are you sure you are handling all of them properly with one try/catch?

-
-
let greeting_file_result = File::open(“hello.txt”);  
let greeting_file = match greeting_file_result {
Ok(file) => file,
Err(error) => panic!("Problem opening the file: {:?}", error),
};
- -

The most verbose of the three shown here and, ironically, the best one. So, first of all, Rust handles the errors using its amazing enums (they are not the same as TypeScript enums!). Without going into detail, what is important here is that it uses an enum called Result with two variants: Ok and Err. As you might guess, Ok holds a value and Err holds…surprise, an error :D.

-

The summary here is that Rust always know where there might be an error. And it force you to deal with it right where it appears (mostly). No hidden ones, no guessing, no breaking app with a surprise face.

-

And this approach is just better. By A MILE.

-

We cannot make TypeScript errors work like the Rust. The limiting factor here is the language itself; it doesn’t have the proper tools to do that.

-

But what we can do is try to make it similar. And make it simple:

-
export type Safe<T> =  
| {
success: true;
data: T;
}
| {
success: false;
error: string;
};
- -

we do need a few try/catches. The good thing is we only need about two, not 100,000:

-
export function safe<T>(promise: Promise<T>, err?: string): Promise<Safe<T>>;
export function safe<T>(func: () => T, err?: string): Safe<T>;
export function safe<T>(
promiseOrFunc: Promise<T> | (() => T),
err?: string,
): Promise<Safe<T>> | Safe<T> {
if (promiseOrFunc instanceof Promise) {
return safeAsync(promiseOrFunc, err);
}
return safeSync(promiseOrFunc, err);
}

async function safeAsync<T>(
promise: Promise<T>,
err?: string
): Promise<Safe<T>> {
try {
const data = await promise;
return { data, success: true };
} catch (e) {
console.error(e);
if (err !== undefined) {
return { success: false, error: err };
}
if (e instanceof Error) {
return { success: false, error: e.message };
}
return { success: false, error: "Something went wrong" };
}
}

function safeSync<T>(
func: () => T,
err?: string
): Safe<T> {
try {
const data = func();
return { data, success: true };
} catch (e) {
console.error(e);
if (err !== undefined) {
return { success: false, error: err };
}
if (e instanceof Error) {
return { success: false, error: e.message };
}
return { success: false, error: "Something went wrong" };
}
}
- -

This is just a wrapper with our Safe type as the return one. But sometimes simple things are all you need. Let’s combine them with the example from above.

-
const request = { name: “test”, value: 2n };  
const body = safe(
() => JSON.stringify(request),
“Failed to serialize request”,
);
if (!body.success) {
// handle error (body.error)
return;
}
const response = await safe(
fetch("https://example.com", {
method: “POST”,
body: body.data,
}),
);
if (!response.success) {
// handle error (response.error)
return;
}
if (!response.data.ok) {
// handle network error
return;
}
// handle response (body.data)
- -

New solution is longer, but it performs better because of the following reasons:

-
    -
  • no try/catch
  • -
  • we handle each error where it occurs
  • -
  • we can specify an error message for a specific function
  • -
  • we have a nice top-to-bottom logic, all errors on top, then only the response at the bottom
  • -
]]>
Technique @@ -2347,6 +2304,49 @@

本快速入门文档参照 Turborepo 2.x 官方文档: https://turbo.build/repo/docs
最后一次编辑:二〇二四年九月二十七日下午六点〇七分

+]]> + + Technique + +
+ + TypeScript With Rust Errors, No Try Catch, Heresy + /2023/04/30/TypeScript-With-Rust-Errors-No-Try-Catch-Heresy/ + +

It’s hard to miss things when you don’t know different things exist

+ +

The first problem is, and personally, I believe it’s the biggest JavaScript problem ever: we don’t know what can throw an error. From a JavaScript error perspective, it’s the same as the following:

+
try {
let data = “Hello”;
} catch (err) {
console.error(err);
}
+ +

JavaScript doesn’t know; JavaScript doesn’t care. You should know.

+

Second thing, this is perfectly viable code:

+
const request = { name: “test”, value: 2n };
const body = JSON.stringify(request);
const response = await fetch("https://example.com", {
method: “POST”,
body,
});
if (!response.ok) {
return;
}
+ +

No errors, no linters, even though this can break your app.

+

Right now, in my head, I can hear, “What’s the problem, just use try/catch everywhere.” Here comes the third problem: we don’t know which one is thrown. Of course, we can somehow guess by the error message, but what about bigger services/functions with many places where errors can happen? Are you sure you are handling all of them properly with one try/catch?

+
+
let greeting_file_result = File::open(“hello.txt”);  
let greeting_file = match greeting_file_result {
Ok(file) => file,
Err(error) => panic!("Problem opening the file: {:?}", error),
};
+ +

The most verbose of the three shown here and, ironically, the best one. So, first of all, Rust handles the errors using its amazing enums (they are not the same as TypeScript enums!). Without going into detail, what is important here is that it uses an enum called Result with two variants: Ok and Err. As you might guess, Ok holds a value and Err holds…surprise, an error :D.

+

The summary here is that Rust always know where there might be an error. And it force you to deal with it right where it appears (mostly). No hidden ones, no guessing, no breaking app with a surprise face.

+

And this approach is just better. By A MILE.

+

We cannot make TypeScript errors work like the Rust. The limiting factor here is the language itself; it doesn’t have the proper tools to do that.

+

But what we can do is try to make it similar. And make it simple:

+
export type Safe<T> =  
| {
success: true;
data: T;
}
| {
success: false;
error: string;
};
+ +

we do need a few try/catches. The good thing is we only need about two, not 100,000:

+
export function safe<T>(promise: Promise<T>, err?: string): Promise<Safe<T>>;
export function safe<T>(func: () => T, err?: string): Safe<T>;
export function safe<T>(
promiseOrFunc: Promise<T> | (() => T),
err?: string,
): Promise<Safe<T>> | Safe<T> {
if (promiseOrFunc instanceof Promise) {
return safeAsync(promiseOrFunc, err);
}
return safeSync(promiseOrFunc, err);
}

async function safeAsync<T>(
promise: Promise<T>,
err?: string
): Promise<Safe<T>> {
try {
const data = await promise;
return { data, success: true };
} catch (e) {
console.error(e);
if (err !== undefined) {
return { success: false, error: err };
}
if (e instanceof Error) {
return { success: false, error: e.message };
}
return { success: false, error: "Something went wrong" };
}
}

function safeSync<T>(
func: () => T,
err?: string
): Safe<T> {
try {
const data = func();
return { data, success: true };
} catch (e) {
console.error(e);
if (err !== undefined) {
return { success: false, error: err };
}
if (e instanceof Error) {
return { success: false, error: e.message };
}
return { success: false, error: "Something went wrong" };
}
}
+ +

This is just a wrapper with our Safe type as the return one. But sometimes simple things are all you need. Let’s combine them with the example from above.

+
const request = { name: “test”, value: 2n };  
const body = safe(
() => JSON.stringify(request),
“Failed to serialize request”,
);
if (!body.success) {
// handle error (body.error)
return;
}
const response = await safe(
fetch("https://example.com", {
method: “POST”,
body: body.data,
}),
);
if (!response.success) {
// handle error (response.error)
return;
}
if (!response.data.ok) {
// handle network error
return;
}
// handle response (body.data)
+ +

New solution is longer, but it performs better because of the following reasons:

+
    +
  • no try/catch
  • +
  • we handle each error where it occurs
  • +
  • we can specify an error message for a specific function
  • +
  • we have a nice top-to-bottom logic, all errors on top, then only the response at the bottom
  • +
]]>
Technique @@ -2414,6 +2414,19 @@ Technique
+ + Linux 下 AMD 显卡屏幕画面闪烁问题修复方案 + /2025/04/20/linux-amd-screen-boom/ + 不知道我们所说的闪烁是不是一个东西,在我的笔记本上,闪烁是指偶发的屏幕中出现部分彩色雪花。

+

我使用 Pop!_OS,此发行版使用 EFI 启动,故而可以在 /boot/efi/loader/loader.conf 中加上:

+
options quiet splash amdgpu.dcdebugmask=0x10 amdgpu.sg_display=0
+ +

对于其他使用 EFI 或 GRUB 启动的发行版也可以添加类似的参数尝试尝试。

+]]>
+ + Technique + +
使用 [@poll error] 实现线程安全的数据结构 /2023/08/15/poll-error-attribute-in-OCaml/ @@ -2447,6 +2460,32 @@
/* The tick thread: posts a SIGPREEMPTION signal periodically */

static void * caml_thread_tick(void * arg)
{
struct timeval timeout;
sigset_t mask;

/* Block all signals so that we don't try to execute an OCaml signal handler*/
sigfillset(&mask);
pthread_sigmask(SIG_BLOCK, &mask, NULL);
while(! caml_tick_thread_stop) {
/* select() seems to be the most efficient way to suspend the
thread for sub-second intervals */
timeout.tv_sec = 0;
timeout.tv_usec = Thread_timeout * 1000;
select(0, NULL, NULL, NULL, &timeout);
/* The preemption signal should never cause a callback, so don't
go through caml_handle_signal(), just record signal delivery via
caml_record_signal(). */
caml_record_signal(SIGPREEMPTION);
}
return NULL;
}

这是因为Multicore OCaml的GC目前需要一个进程(或一个Domain)中的所有线程一起参与以避免并发访问。如果一个线程在system call上被阻塞,那么整个Domain就会被卡住,直到该线程可以参与当前的垃圾收集。为了避免这个问题,tick 线程可以代替被阻塞的线程执行垃圾收集操作。

+]]> + + Technique + +
+ + UUID v7 是如何加快 RDBMS 索引速度的 + /2025/04/13/uuidv7-rdbms/ + UUID v7 之所以能显著提升关系型数据库(尤其是采用聚集索引的 MySQL InnoDB)在插入和查询速度,主要归功于它在 ID 中引入了“可排序的时间戳前缀”,从而大幅减少了 B-Tree 索引页分裂(page split)和数据碎片化。这里分几点来说:

+

一、 聚集索引(Clustered Index)的插入机制

+

在 InnoDB 中,聚集索引的叶子节点同时存储了行数据,且按照索引键(主键)顺序物理排序。

+

当新记录的主键完全随机(如 UUID v4)时,每次插入都会随机落在 B-Tree 的不同叶子页,导致频繁的页分裂和指针重排,而页分裂和随机 I/O 会带来大量的磁盘写放大和缓存抖动(cache churn),削弱吞吐并拉高延迟。

+

二、UUID v7 的时间排序特性

+

UUID v7 在高位(前 48 位)嵌入了以毫秒级精度的 Unix 时间戳,剩下的位用于随机数或序列号,这样生成的 ID 保持全局唯一性的同时,随着时间自然递增(即“近似单调递增”),新插入的记录几乎总是追加到 B-Tree 的最右端叶子节点。

+

参见 dbaplus.cn 的分析:

+
+

“UUID v7 的创新之处在于其时间排序特性,它在前 48 位中嵌入了以毫秒为单位的 Unix 时间戳……可能在插入和查询操作上提供更好的性能”【1】。

+
+

三、降低页分裂与碎片化

+

顺序或近似顺序的主键能使叶子节点连续增长,极少触发页分裂,并且更少的页分裂意味着更低的写放大(write amplification)和更稳定的插入延迟,同时,减少了空洞和链表重排,提高了磁盘和内存缓存的命中率。

+

四、提升查询局部性与缓存命中

+

因为数据物理上是按时间顺序紧凑写入,时间范围查询(如 “最近 1 小时的日志”)可以快速定位连续的叶子页,I/O 更聚集,内存缓冲池(buffer pool)或操作系统页缓存能更有效地缓存最近热数据,进一步加速查询。

+
+

Rimon Tawadrous 在其 GitHub repo 中的测试,对比 100 万条逐条插入实验,UUID v7 相较 UUID v4 在单线程插入上速度快约 3.24%,多线程下更可观【1】。

+
+

参考链接
[1] “为什么 UUID 7 比 UUID 4 更适合作为 RDBMS 的聚集索引?” dbaplus.cn
https://dbaplus.cn/news-160-6313-1.html
[2] “PostgreSQL and UUID as primary key” maciejwalkowiak
https://maciejwalkowiak.com/blog/postgres-uuid-primary-key/
[3] “Optimised UUIDs in mysql” stitcher
https://stitcher.io/blog/optimised-uuids-in-mysql
[3] “Storing UUID Values in MySQL” percona
https://www.percona.com/blog/store-uuid-optimized-way/

]]>
Technique @@ -2536,36 +2575,6 @@

这世上也不是所有事都算得准的。

云仰望着太阳,羡慕他的炙热,或许太阳也在仰望着云,渴求他的停留。

地球距离太阳1.5亿公里,如无意外,两者此生不会相遇,但从此以后,我与世间美好再也不会分离。

-]]> - - gallery - -
- - 二〇二三年十二月二日 - /2023/12/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%BA%8C%E6%97%A5/ - 夏日凌晨的海风,裹挟着季风带的温热的潮气不远万里奔赴而来,搅碎了一汪流动的星星。

-

天空泛起一丝鱼肚白,那是每年夏至,凌晨四点多就会早起的日出。

-

而身后那栋为我而建的世界上独一无二的小屋子,正通宵达旦地亮着灯火,里面是我的痕迹,我的热爱,我的温暖和祝福。

-

身前,我的山林和小狗,正笨拙地试图从自然的馈赠里找到那份属于它们的礼物。

-

它们那样爱着我,那样忠诚于我。

-

那一刻,我突然就想起了曾经在书上看过的一句很喜欢的话——“世界先爱了我,我不能不爱他.”

-

曾经在冬季日出的时候,我见过海岸线浮满碎冰的模样,那是连太阳都会显得寂寥和落寞的冷清。

-

可是太阳始终当着太阳,守着一个恒星的职责,不知疲倦地用自己炽热的温度和光芒试图唤醒沉睡的冬日。

-

直到终于有一天,有人在冬夜里复苏,爱上了那个比夏天更炽烈的温度,然后海浪成了新娘白色的花环,我成了太阳一生的爱人。

-

所以我始终愿意相信,是这个世界先温柔地爱了我。

-

哪怕世界给予我的这份爱,在最初的时候,来得并不那么明显,也并不那么浓烈,我也曾因此孤独过,无助过,迷茫过,放弃过。

-

可是那份爱最终还是随着冰雪消融,春暖花开,随着夏天剧烈摇晃过后的气泡水,滋滋地冒了出来,连盖上盖子,也没有办法捂住。

-

所以我拥有了世界上最好的义无反顾的爱。

-

看着前方,轻轻叫了一声:“毛毛”

-

狗狗立马回了头,和乍出的日光,和突然转动的风力发电机,和突然被风吹动的山林,同步发生。好像只要我一声令下,这个世界就愿意为我而生动。

-

可这世间哪里会在乎茫茫人海中这不值一提的爱

-

我们都只不过是平凡世界里平凡生活着的人们,如果非要说有什么不同,那就是我只爱着这个世界而已。

-

于是我看着那只大笨狗,看着并没有被虚化成背景的世界,温柔地弯起了唇角:“有句话今天我一直忘记告诉你了。”

-

狗狗叼起一根树枝,歪头不解地看着我。

-

然后我就在山峰浮现出第一缕阳光时,笑着对这个世界说:“我爱你,会永远爱你,永远最爱你。”

-

我爱这个因为有我而变得温柔的世界。

-

这将是我与周遭的一切,热爱一生,共度一生的地方。

]]>
gallery @@ -2617,6 +2626,36 @@

还是广袤宇宙中的一颗有名有姓的星星,

宇宙、银河、太阳,都不重要。

热爱这个世界,是我成长里最美妙的勇敢事迹。

+]]> + + gallery + +
+ + 二〇二三年十二月二日 + /2023/12/02/%E4%BA%8C%E3%80%87%E4%BA%8C%E4%B8%89%E5%B9%B4%E5%8D%81%E4%BA%8C%E6%9C%88%E4%BA%8C%E6%97%A5/ + 夏日凌晨的海风,裹挟着季风带的温热的潮气不远万里奔赴而来,搅碎了一汪流动的星星。

+

天空泛起一丝鱼肚白,那是每年夏至,凌晨四点多就会早起的日出。

+

而身后那栋为我而建的世界上独一无二的小屋子,正通宵达旦地亮着灯火,里面是我的痕迹,我的热爱,我的温暖和祝福。

+

身前,我的山林和小狗,正笨拙地试图从自然的馈赠里找到那份属于它们的礼物。

+

它们那样爱着我,那样忠诚于我。

+

那一刻,我突然就想起了曾经在书上看过的一句很喜欢的话——“世界先爱了我,我不能不爱他.”

+

曾经在冬季日出的时候,我见过海岸线浮满碎冰的模样,那是连太阳都会显得寂寥和落寞的冷清。

+

可是太阳始终当着太阳,守着一个恒星的职责,不知疲倦地用自己炽热的温度和光芒试图唤醒沉睡的冬日。

+

直到终于有一天,有人在冬夜里复苏,爱上了那个比夏天更炽烈的温度,然后海浪成了新娘白色的花环,我成了太阳一生的爱人。

+

所以我始终愿意相信,是这个世界先温柔地爱了我。

+

哪怕世界给予我的这份爱,在最初的时候,来得并不那么明显,也并不那么浓烈,我也曾因此孤独过,无助过,迷茫过,放弃过。

+

可是那份爱最终还是随着冰雪消融,春暖花开,随着夏天剧烈摇晃过后的气泡水,滋滋地冒了出来,连盖上盖子,也没有办法捂住。

+

所以我拥有了世界上最好的义无反顾的爱。

+

看着前方,轻轻叫了一声:“毛毛”

+

狗狗立马回了头,和乍出的日光,和突然转动的风力发电机,和突然被风吹动的山林,同步发生。好像只要我一声令下,这个世界就愿意为我而生动。

+

可这世间哪里会在乎茫茫人海中这不值一提的爱

+

我们都只不过是平凡世界里平凡生活着的人们,如果非要说有什么不同,那就是我只爱着这个世界而已。

+

于是我看着那只大笨狗,看着并没有被虚化成背景的世界,温柔地弯起了唇角:“有句话今天我一直忘记告诉你了。”

+

狗狗叼起一根树枝,歪头不解地看着我。

+

然后我就在山峰浮现出第一缕阳光时,笑着对这个世界说:“我爱你,会永远爱你,永远最爱你。”

+

我爱这个因为有我而变得温柔的世界。

+

这将是我与周遭的一切,热爱一生,共度一生的地方。

]]>
gallery -- cgit v1.2.3