TiDBさわってみた！


## 自己紹介

初投稿なので、自己紹介。
ワクトのオーガです。
これから、バックエンドのキャッチアップした関連の記事を投稿していきたいと思ってます。
よろしくお願いします！！！🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉

## TiDBとは？

- オープンソースの分散データベース。
- 読み方は、タイディービィー。
- PingCAP社が開発している。
- MySQLと互換があり、同じように使用可能。

- 高い拡張性
- シャーディングが自動で行われる

[公式サイトはこちら](https://www.pingcap.com/)

### そもそも、シャーディングって？？？

(Google AI Bardによると)
分散データベースにおけるシャーディングとは、データベースのデータを複数のノードに分散して保存する技術です。これにより、データベースのパフォーマンスを向上させ、データの可用性を高めることができます。

- シャーディングの種類
  - 水平分散：データを**キーの値**に基づいて分散します
  - 垂直分散：データを**属性の値**に基づいて分散します

- シャーディングの用途
  - 水平分散は、データの検索や更新のパフォーマンスを向上させるのに適しています
  - 垂直分散は、データのサイズが大きくなり、処理が重くなった場合に適しています

- シャーディングのメリット／デメリット

|メリット|デメリット|
|----|-----|
|パフォーマンスの向上|複雑さの増加|
|可用性の向上|コストの増加|
|スケーラビリティの向上|パフォーマンスの低下|
|柔軟性の向上||

:::note warn
  もちろん、通常のDBと同様、むやみなパフォーマンスチューニングは逆効果になりうる。
:::

#### 水平分散を図解

- ユニークなキー（ここでいうid）を1〜1000、1001〜2000、2001〜3000・・・というようにノードに分散して保存する。

![水平分散説明](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1312905/7fde92f8-4df6-7abe-99da-5a8f6a883100.png)

#### 垂直分散を図解

- カラムごとに分散して保存する
- よく参照されるカラムを切り出して別ノードに保存することでパフォーマンスの改善が期待できるっぽい。（ここは、これから調べる）

![垂直分散説明](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1312905/2957f90f-20d6-df8a-f32b-df8232442571.png)
  
## TiDBとRDBの違い

- スケールイン／スケールアウトが容易

- 分断耐性が高い（ノードが1個落ちても、サービス継続可能）
  
### 以下比較表

|DBMS|一貫性|可用性|分断耐性|ACIDトランザクション|拡張性の高さ|
|:----:|:---:|:---:|:----:|:----:|:----:|
|MySQL|○|○|×|○|△|
|TiDB|○|△|○|○|○|

:::note info
MySQLの欠点である分断耐性が、分散データベースであるが故に、NewSQL(TiDB)では、強みとなっている。
:::

## DBへの接続方法

:::note info
Goによる接続例
:::

- gormもサポートしているので、今までと同じコードで問題なし。

~~~go
package main

import (
  "gorm.io/gorm"
  "gorm.io/driver/sqlite"
)

type Product struct {
  gorm.Model
  Code  string
  Price uint
}

func main() {
  db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
  if err != nil {
    panic("failed to connect database")
  }

  // Migrate the schema
  db.AutoMigrate(&Product{})

  // Create
  db.Create(&Product{Code: "D42", Price: 100})

  // Read
  var product Product
  db.First(&product, 1)
}
~~~

## TiDBをローカルに立ててみた

- 基本、公式にあるやつを実行

~~~bash

curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
source ~/.zshrc
tiup playground

~~~

#### 以下の表示が出れば成功🎉 🎉 🎉 

~~~bash
🎉 TiDB Playground Cluster is started, enjoy!
~~~

- 別端末を開いて、MySQLと同じく接続する！！！

~~~bash
# portは、4000 で TiDBへ接続する
mysql --host 127.0.0.1 --port 4000 -u root

Your MySQL connection id is 11
Server version: 5.7.25-TiDB-v7.2.0 TiDB Server (Apache License 2.0) Community Edition, MySQL 8.0 compatible

# あとは、MySQLと同じ
mysql>　CREATE DATABASE user;
mysql> use user;

Database changed

mysql> CREATE TABLE `user` (
->    `id` INT(255) NOT NULL AUTO_INCREMENT,
->    `name` VARCHAR(255) NOT NULL,
->    `password` VARCHAR(255) NOT NULL,
->    `created_at` DATETIME NOT NULL,
->    `updated_at` DATETIME NOT NULL,
->    PRIMARY KEY (`id`)
->    );

Query OK, 0 rows affected (0.10 sec)

mysql> DESC user;
+------------+--------------+------+------+---------+----------------+
| Field      | Type         | Null | Key  | Default | Extra          |
+------------+--------------+------+------+---------+----------------+
| id         | int(255)     | NO   | PRI  | NULL    | auto_increment |
| name       | varchar(255) | NO   |      | NULL    |                |
| created_at | datetime     | NO   |      | NULL    |                |
| updated_at | datetime     | NO   |      | NULL    |                |
+------------+--------------+------+------+---------+----------------+
4 rows in set (0.00 sec)

mysql> INSERT INTO `user` (`name`,`created_at`,`updated_at`) VALUES ("テスト",NOW(),NOW());

Query OK, 1 row affected (0.01 sec)

mysql> select * from user;
+----+-----------+---------------------+---------------------+
| id | name      | created_at          | updated_at          |
+----+-----------+---------------------+---------------------+
|  1 | テスト    | 2023-07-23 21:14:13 | 2023-07-23 21:14:13 |
+----+-----------+---------------------+---------------------+
1 rows in set (0.00 sec)

mysql> exit
~~~

## minikube で ローカルにTiDBを立ててみる

M1 Mac　メモリ8GB のせいなのか、メモリが足らずTiDBが起動せず。
Dockerのメモリ上限とかいじっても改善せず。

今度、リベンジ。このために、お家k8sやっても良い。。。

## まとめ

### 良かった点

- 今まで、難しそうと敬遠してきたが、意外と使うだけならそうでもない。むしろ楽しい😍😍😍
- 拡張性も高いし、個人開発でのDBも、今後キャッチアップ含みで導入して慣れていきたい。
- シャーディング？？？分散データベース？？？だった点が、少し理解が進んだ！！！

### いまいちだった点

- kubernetes上で構築したかったが、minikubeのメモリの関係上できなかった。
- スケールイン／スケールアウトのしやすさが体験できなかった。

### 次に向けて

- kubernetes上でできなかったのか悔しいのでリベンジする
- TiDB cloudは次回使ってみる。
- 個人開発に導入する。

## 参考

https://zenn.dev/taki8545/articles/6fd377ef9bd883

https://docs.pingcap.com/tidb/dev/quick-start-with-tidb

https://www.pingcap.com/tidb/

https://tidbcloud.com/free-trial?__hstc=86493575.a6f6bd890e8cb7a56825a3d6bf4da768.1690080592786.1690080592786.1690080592786.1&__hssc=86493575.3.1690080592786&__hsfp=3567315901&_gl=1*cmvipz*_ga*MTIwMDA2NTYxMi4xNjkwMDMwOTEz*_ga_9FRXHHPYVY*MTY5MDA4MDU5MS4xLjEuMTY5MDA4MDkzMy4zMi4wLjA.&_ga=2.108647105.29318933.1690030913-1200065612.1690030913

https://gorm.io/ja_JP/docs/index.html

## 余談

久しぶりにminikube起動したら、絵文字すごっwww

~~~bash

MacBook-Air:qiita-article-org $ minikube start
😄  Darwin 13.4 (arm64) 上の minikube v1.28.0
🎉  minikube 1.31.1 が利用可能です！次の URL からダウンロードしてください: https://github.com/kubernetes/minikube/releases/tag/v1.31.1
💡  この通知を無効にするためには、'minikube config set WantUpdateNotification false' を実行します

✨  既存のプロファイルを元に、docker ドライバーを使用します
👍  minikube クラスター中のコントロールプレーンの minikube ノードを起動しています
🚜  ベースイメージを取得しています...
🤷  docker 「 minikube 」 container がありません。再生成します。
🔥  docker container (CPUs=2, Memory=2200MB) を作成しています...
🐳  Docker 20.10.20 で Kubernetes v1.25.3 を準備しています...
🔎  Kubernetes コンポーネントを検証しています...
    ▪ gcr.io/k8s-minikube/storage-provisioner:v5 イメージを使用しています
💡  アドオンを有効にした後、「minikube tunnel」を実行することで、ingress リソースが「127.0.0.1」で利用可能になります
    ▪ k8s.gcr.io/ingress-nginx/controller:v1.2.1 イメージを使用しています
    ▪ k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1 イメージを使用しています
    ▪ k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1 イメージを使用しています
🔎  ingress アドオンを検証しています...
🌟  有効なアドオン: storage-provisioner, default-storageclass, ingress

❗  /usr/local/bin/kubectl のバージョンは 1.22.5 で、Kubernetes 1.25.3 と互換性がないかもしれません。
    ▪ kubectl v1.25.3 が必要ですか？ 'minikube kubectl -- get pods -A' を試してみてください
🏄  終了しました！kubectl がデフォルトで「minikube」クラスターと「default」ネームスペースを使用するよう設定されました
MacBook-Air:qiita-article-org $ 

~~~