OmniAICreator/Qiita-1.07M huggingface dataset:
weak selfがstructでは使用できず、classで使用できるのはなぜ？

# weak selfがstructで使用しようとした時に起こったエラー

🟥エラー：'weak' may only be applied to class and class-bound protocol types
'weak'は、クラスおよびクラスにバインドされたプロトコルタイプにのみ適用できるというエラーが起こる。

# structとclassの違いとweak self

### ⚫︎structは値型

### ⚫︎classは参照型

参照型は3つの参照方法がある！
1.強参照
デフォルトはstrong
2.弱参照
weak
参照先が存在しない場合に参照しようとされると自動でnilになってる
3.非所有参照
unowned
参照先が存在しない場合に参照しようとされると解放済みへのアクセスとなりクラッシュする


### structにweak selfが適用できない理由

weakは参照型のための修飾子であり、構造体などの値型とは異なる。
値型はコピーによって割り当てられ、参照カウントは適用されないので、weak修飾子は意味を持ちません。
以下のようなエラーになります。

```swift
struct S {
    private var closure: (() -> Void)?
    private var count = 0

    init() {
        closure = createClosure()
    }

    func createClosure() -> (() -> Void) {
//🟥エラー：'weak' may only be applied to class and class-bound protocol types, not 'S'
        return { [weak self] in self?.count += 1 }
    }
}

var s: S? = S() 
s = nil  
```

### classでweak selfの適用例

参照型では、同じオブジェクトに対して複数の参照を持つことができる。
オブジェクトは、最後の強い参照がそのオブジェクトを参照しなくなった時点で解放されます。
classは参照型であるため、weakは参照型のための修飾子が適用できます！
以下のようにclassでweak selfを使用すると、参照先が存在しない場合に参照しようとされると自動でnilになってくれるので、循環参照を防ぐことができます！

```swift
class C {
    private var closure: (() -> Void)?
    private var count = 0

    init() {
        closure = createClosure()
    }

    func createClosure() -> (() -> Void) {
        return { [weak self] in self?.count += 1 }
    }
}

var c: C? = C()
c = nil 
```

# 参考文献

https://zenn.dev/mhackit/articles/a0b1c6e780c3c6aabe45

https://qiita.com/yimajo/items/892bd2fe1ccb808ffe49

https://stackoverflow.com/questions/38841127/why-can-the-keyword-weak-only-be-applied-to-class-and-class-bound-protocol-typ

https://www.swiftlangjp.com/language-guide/automatic-reference-counting.html
競プロの初めの10問を解いてみた

# AtCoder Beginners Selection

初心者向けの問題が10問厳選されており、始めるにはもってこいの問題集。


https://atcoder.jp/contests/abs

いろんな方が、書いてますが自分も取り組んでみた感想を書きます。

以下自己解答。
他にも色々な解法があるのですが、自分が解けた(答えを見て理解できた)範囲で書きます。

# PracticeA - Welcome to AtCoder

```python
# -*- coding: utf-8 -*-
# 整数の入力
a = int(input())
# スペース区切りの整数の入力
b, c = map(int, input().split())
# 文字列の入力
s = input()
# 出力
print(a+b+c,s)
```


# ABC086A - Product

```python

a,b= map(int,input().split())

if (a*b)%2:
  print('Odd')
else:
  print('Even')
```

# ABC081A - Placing Marbles

```python
s = str(input())
cnt = 0
for i in s:
  if i == '1':
    cnt+=1
print(cnt)
```

# ABC081B - Shift only

```python
n = int(input())
li = list(map(int,input().split()))
cnt = 0
while all(i % 2 == 0 for i in li):
  li = [i // 2 for i in li]
  cnt +=1
print(cnt)
```

# ABC087B - Coins

```python
a = int(input())
b = int(input())
c = int(input())
x = int(input())
print(
    sum(500*i+100*j+50*k==x for i in range(a+1)for j in range(b+1)for k in range(c+1))
)
```

sum関数に気づけるか、3重のforループになったけど通りました。

# ABC088B - Card Game for Two

```python

n=input()
a=list(map(int,input().split()))

a.sort(reverse=True)
al,bo=0,0
for i,v in enumerate(a):
  if i%2==0:
    al+=v
  else:
    bo+=v

print(al-bo)
```

# ABC085B - Kagami Mochi

```python
n = int(input())
hash = []
for _ in range(n):
  a = int(input())
  hash.append(a)
  
print(set(hash))
```
forをブランクで回せることに気づいた。

# 	ABC085C - Otoshidama

```python

n, y = map(int, input().split())
for i in range(n + 1):
    for j in range(n-i+1):
        if 10000*i + 5000 *j + 1000*(n-j-i) == y:
            print(i, j, n - i - j)
            exit()
print("-1 -1 -1")
```



# ABC049C - 白昼夢

```python

s = input()
# erを先にすること
list = ["eraser", "erase", "dreamer", "dream"]

for i in list:
  s = s.replace(i, "")
  
if s:
  print("NO")
else:
  print("YES")
```

これこそ、頭を使う問題。


# 	ABC086C - Traveling

```python
n = int(input())

prev_t, prev_x, prev_y = 0, 0, 0

for _ in range(n):
  t, x, y = map(int, input().split())
  
  dist = abs(x - prev_x) + abs(y - prev_y)
  time_diff = t - prev_t
  
  if dist > time_diff or (time_diff - dist) % 2 != 0:
    print("No")
    exit()
  
  prev_t, prev_x, prev_y = t, x, y

print("Yes")
```

Cは難しいので、今後もっと解いていきたいですね。


# 感想
正直難しい。全問解けたわけではないですが、解けたものもありました。
わからないものは、考えてもわからないので答えを見てしまいましたが
いろんな書き方があるし、知らない関数の使い方も学びました。


## 標準入力の取り方
input()で1つは取ることが可能。
ですが、連続するデータの取得方法に悩んだり、リストに入れることが最初は戸惑いました。

## mapの使い方
標準入力の取得で頻繁に使うことになったmap
mapを使うとリストに関数を適用できるため、intを使い変換をしたりしました。
標準入力では必須になりがち。

## 内包表記の使いかた(結構頻繁に)
forで書くと複数行になるものがあるため、内包型で1行にまとめる。
これはリファクタリングで使えるなと感じました。
💩クソアプリハッカソン出てみた！


# はじめに

💩💩💩

:::note info

本記事は、クソアプリアドベントカレンダー 2023 9 日目の記事です。

:::

# つくったもの

何の生産性もないただ以下の「モンハン総選挙」のサイトをクローンして、
データや見た目をいじっただけのアプリです。

はい、くそつまらん！

無駄にデプロイもしてます！

https://kuso-app-20231123.web.app/

<br>

![スクリーンショット 2023-12-05 7.10.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1312905/0c3ca573-ddcd-5475-1c57-c4b4577f6e6c.png)

<br>

無駄に絞り込みとか付けちゃったりして

![スクリーンショット 2023-12-05 7.10.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1312905/d1ea0aa6-f06b-e398-5972-7b089fd1ca4a.png)

# やりたかったこと

- AI を使用して、モンスター相性診断
- モンスターをクリックしたら、モンスターのふんが表示される
- ラングロトラ、野球しようぜゲーム

もっと面白いもの作ればよかった。

# よかったこと

短い時間の中で、何作るか考えて、一応、作り切ることができた点は良かった。
しかも、得意ではない、フロントエンドの開発で。

それは、今年、しっかり、React や Next.js をキャッチアップしつつ、HTML/CSS も振り返った成果だと思うので、
ポジティブに捉えていきたい。

# まとめ

- クソアプリハッカソンを開催してくれた運営の皆様ありがとうございました
- 初めてにしては、短時間でアプリを作ることができ、そこそこな 1 年の成長を実感できたのでよしとします
- 来年も開催していただけるなら、もっと面白い技術の無駄遣いなアプリを作りたい

こんなクソアプリののクソ短い記事をご覧いただき、ありがとうございました！
まぁ、頑張ったんなと思う方は、いいね、フォローよろしくお願いいたします。

では、また来年のクソアプリアドベントカレンダーで。

💩💩💩
住所はわかるんだけど、郵便番号なんだっけ  #GAS

## 住所はわかるんだけど郵便番号なんだっけ
↑ということありませんか？ 私は自分の住所は覚えることができますが、郵便番号を覚えられない人です。
毎回、「XXX県 XXX市 住所」と検索するのが絶妙に億劫、、、だったので、住所を書くと郵便番号を返信してくれるLINEBotを作成してみました。 
※なお私の技術の問題で、東京都内の住所のみになっております。

## 使い方

https://x.com/mmmrym112/status/1731798352696647805?s=20

①東京都〇〇（市区町村）△△の△△の部分をLINEBotに送る。
②合致した場合、郵便番号を返してくれる。(合致していないと無視です。)

## 作り方
こちらのコードを参考にしました。

https://www.yukibnb.com/entry/linemessagingapi_gas

住所と郵便番号を[郵便局のHP](https://www.post.japanpost.jp/zipcode/download.html)から拝借しました。こちらをスプレッドシートにコピペします。

![img5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3565590/9982e671-3fed-4a78-3eee-3e79fc75e46c.png)
↑このような感じ、本当は〇〇（都道府県）XX(市区町村)△△と検索したかったのですが、複数の検索条件のやり方がわからず、△△部分だけ残しました。

## さいごに
Googleを開いて検索する手間が絶妙に面倒&まあまあな頻度で起こるので、便利ですね。 あと郵便番号だけ返してくれるので、コピペし易い。
でもやはり、東京都以外の郵便番号も検索したい、、ので複数条件で郵便番号を絞れるようにしたいです。
公式から配布されるデザインリソースがいつでも正しいとは限らないから実際の挙動を確認しようと思った話

## この記事の概要

Figma Community には、Apple 公式から iOS と iPad OS 向けのデザインデータが配布されています。

https://www.figma.com/community/file/1248375255495415511/apple-design-resources-ios-17-and-ipados-17

このデータと、[Apple Developer Documentation](https://developer.apple.com/documentation/SwiftUI/View/alert(_:isPresented:actions:)-1bkka)をあわせて見ていた際に気づいたことがありました。
その事例をもとに、UI デザイナーとしてのデータ作りの心構えを記事にしてみます。

## Figma データの中身

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/90fb6cb2-f2d1-b932-ee9d-4902180858b2.png)

このような作りになっていました。
今回の記事に関係のある箇所を抜き出すと

- ボタンが 1 つ、2 つ（横並び）、2 つ（縦並び）、3 つというバリエーション
- 1 番上、あるいは右側のボタンの文字は太い

## コードによる動き

SwiftUI を基準にします。
ドキュメントを見つつ、自分でも書きながら検証していました。

https://developer.apple.com/documentation/SwiftUI/View/alert(_:isPresented:actions:)-1bkka

| 説明 | 画像 | 結果 |
| --- | --- | --- |
| ボタン 2 つ、短いラベル | ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/be1dbc48-5cf4-5221-e242-742146c50f08.png) | 横並び、太字無し |
| ボタン 2 つ、片方のラベルが長い | ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/2cc29be6-90ed-4f1b-cfcf-c64b6fd0a615.png) | 縦並び、太字無し |
| ボタン 3 つ | ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/e84e612d-2a00-6efc-39fc-288ec93420b2.png) | 縦並び、太字無し |
| `ボタン 2` に `role: .canceled` | ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/efb09b8a-66d2-acd8-178f-20f5b3815d31.png) | `ボタン 2` が最後に、太字 |
| `ボタン 2` に `role: .destructive` | ![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214677/8a5506ba-5963-bd27-7ec2-fd202ba0336b.png) | 順番そのまま、新たに太字の `Cancel` が出現 |

公式ドキュメントによれば「デフォルトのアクションはより目立つように表示される」とのことで、それを表したのが Figma データでいう「1 番上、あるいは右側のボタンの文字は太い」表現だと思います。

ただ、実際には全部細いウェイトで表示されていることもあれば、キャンセルが太字になっていることもあり、Figma データだけを鵜呑みにすると多少実装と齟齬が出そうです。

## 学び

今回は SwiftUI で検証していましたが、UIKit だと preferred action がありそちらを設定すれば太字の設定もできそうな気配を感じています（未検証）。

ただいずれにしても、そんな細かい違いまでデザインデータで再現して配布してもらえることは少ないです。[^1]

[^1]: Human Interface Guidelines に限らず、Material Design であっても実際のスタイルと Figma データが違う、なども過去に遭遇しました。詳しくは忘れてしまいましたが……なんなら Material の方がドキュメントごとの揺れや時期による違いが大きいまであったと思います。

公式からのデータですらこれなので、非公式に配布されているコンポーネントライブラリなどは信頼し過ぎない方が良いのでしょう。
コードでは取れない引数なのに、Figma では variant 化されている場合なども見かけたことがあり、そういった細かい部分からも綻びは生まれがちです。

コードとしても動かして検証するなり、逆にいっそ長期の運用は諦めて「いつでも捨てられる」ようなモックアップにするなり、思想を持った上でデザインデータを作る方が良いと思います。
pythonでの部品管理テスト②

import cv2
import numpy as np
import time
from tkinter import simpledialog
import tkinter as tk

def preprocess_image(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    return blurred

def detect_changes(image1, image2, points, threshold=30, area_size=20):
    diff = cv2.absdiff(image1, image2)
    _, thresh = cv2.threshold(diff, threshold, 255, cv2.THRESH_BINARY)
    changes = {}

    for pt, tool_name in points.items():
        x, y = pt
        roi = thresh[max(0, y - area_size):y + area_size, max(0, x - area_size):x + area_size]
        if cv2.countNonZero(roi) > 0:
            changes[pt] = tool_name

    return changes

def ask_tool_name(x, y):
    root = tk.Tk()
    root.withdraw()  # Hide the main window
    tool_name = simpledialog.askstring("Tool Name", "Enter the name of the tool:", parent=root)
    root.destroy()
    return tool_name

def click_event(event, x, y, flags, params):
    if event == cv2.EVENT_LBUTTONDOWN:
        tool_name = ask_tool_name(x, y)
        if tool_name:
            points[(x, y)] = tool_name
            print(f"Selected Point: ({x}, {y}) - Tool: {tool_name}")

points = {}

cap = cv2.VideoCapture(0)
cv2.namedWindow("Camera Feed")
cv2.setMouseCallback("Camera Feed", click_event)

ret, last_frame = cap.read()
last_frame = preprocess_image(last_frame)
last_check = time.time()

while True:
    ret, frame = cap.read()
    if not ret:
        break

    processed_frame = preprocess_image(frame)
    if time.time() - last_check > 60 and points:
        changes = detect_changes(last_frame, processed_frame, points)
        for pt, tool_name in changes.items():
            print(f"{tool_name} is missing at {pt}")
            cv2.putText(frame, f"{tool_name} is missing!", pt, cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

        last_check = time.time()

    last_frame = processed_frame

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

    cv2.imshow("Camera Feed", frame)

cap.release()
cv2.destroyAllWindows()
Re ： 1からはじめるSvelte入門【part 2】


# はじめに

本記事は、svelte 初心者が一から入門して、Web アプリを１人で構築できるようになるためのハンズオン形式の投稿です。

# 想定読者

:::note warn

以下の知識がある前提で進めていきます。

- HTML、CSS が分かること
- バックエンドは解説しないので、何かしらの言語でバックエンドの処理を書けること
- Node.js の環境があること

:::

- バックエンドエンジニアだけど、フロントエンドは苦手な方
- Web エンジニアを目指す方
- Svelete に興味を持った方

# 環境

開発環境は、以下の想定で進めていきます。

- OS :
  - ProductVersion : 14.0
  - BuildVersion : 23A344
- Node.js : v18.16.1
- npm : 9.5.1
- Svelte : 4.0.5

# 参考リポジトリ

https://github.com/o-ga09/tutorial-Svelte/commits/

part 毎のソースコードをタグで作成しておりますので、part 毎のソースコードが必要な方はダウンロードしてご使用ください。

# 第 2 回目

## カウンターアプリ

### やること

- Tailwind の導入
- `<button on:click>`の使い方
- Reactive な変数の使い方

### 想定作業時間

30 分

### 成果物

![スクリーンショット 2023-12-04 23.30.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1312905/ff731ab2-76c3-ea53-208f-b0ebf27c417c.png)

### 使用する構成

- Svelte
- SvelteKit
- TailwindCSS

## 手順解説

<details><summary>解説を見る</summary>

1 . Tailwind 導入

```bash
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
```

```diff_javascript:tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
- content: [],
+ content: ['./src/**/*.{html,js,svelte,ts}'],
  theme: {
    extend: {},
  },
  plugins: [],
}
```

```css:app.css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

```diff_html:layout.svelte
<script>
	import './styles.css';
+	import '../app.css';
</script>

<div class="app">
	<main>
		<slot />
	</main>
</div>

<style>
	/* root layout style */
	main {
		display: flex;
		align-items: center;
		justify-content: center;
		width: 100%;
		height: 100vh;
	}
</style>

```

<br>

2 . +page.svelte 修正

```html:+page.svelte
<script>
	let count = 0;

	const plusButton = () => {
		count = count + 1;
	};

	const minusButton = () => {
		count = count - 1;
	};
</script>

<svelte:head>
	<title>Home</title>
	<meta name="description" content="Svelte demo app" />
</svelte:head>

<div class="counter">
	<h1 class="text-center">カウンターアプリ</h1>
	<div
		class="
		flex
		items-center
		justify-center
		w-64
		h-96
		text-5xl
		font-bold
		bg-lime-400
		rounded-lg
		m-4
	  "
	>
		{count}
	</div>
	<div class="flex items-center justify-center h-20">
		<button
			class="
		  h-full
		  w-20
		  m-4
		  bg-cyan-400
		  border-cyan-400
		  rounded-lg
		  text-3xl
		"
			on:click={plusButton}
		>
			+
		</button>
		<button
			class="
		  h-full
		  w-20
		  m-4
		  bg-cyan-400
		  border-cyan-400
		  rounded-lg
		  text-3xl
		"
			on:click={minusButton}
		>
			-
		</button>
	</div>
</div>

```

上記のように、Svelte では、`<Button>`タグに`on:click`などの特別なプロパティ
が最初からついています。

また、カウントの変数も React のように`useState`のような特別な関数を使用しなくても、
ただ、`let count = 1`でカウンターアプリを実装できてしまいます。

:::note info

今回の記事におけるポイントは、`<button on:click={}>`の使い方と、
Svelte における状態を表す変数の使い方をマスターしました。

:::

</details>

# まとめ

いかがだったでしょうか？これから、私自身、Svelte を使用して Web アプリ構築するために本記事を投稿していこうと考えております。
よろしければ、いいね、フォローよろしくお願いいたします。

一緒に、Svelte について学んでいきましょう！

## 前回の記事はこちら

https://qiita.com/o-ga/items/6de543a495770a51956f
pythonでの部品管理テスト

内部カメラの起動: コンピュータの内部カメラを使用してリアルタイムのビデオフィードを取得します。

画像の表示: カメラから取得した画像をリアルタイムで画面に表示します。

マウスクリックによる座標の選択: ユーザーがマウスでクリックした座標を取得し、それを記録します。これらの座標は、変化を検出するための基準点として使用されます。

画像の前処理: 撮影した画像をグレースケールに変換し、ガウシアンぼかしを適用してノイズを減少させます。

定期的な画像撮影と変化のチェック: プログラムは1分ごとに画像を撮影し、前回の画像との差分を計算します。この差分は変化の検出に使用されます。

指定された座標周辺での変化の検出: 前回と今回の画像の差分を取り、ユーザーが指定した座標周辺で変化があるかどうかをチェックします。変化がある場合、プログラムは変化が検出されたことを出力します。

プログラムの終了: ユーザーがキーボードの 'q' キーを押すと、プログラムは終了し、カメラと関連するウィンドウが閉じられます。

import cv2
import numpy as np
import time

def preprocess_image(image):
    """ 画像の前処理を行う関数 """
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    return blurred

def detect_changes(image1, image2, points, threshold=30, area_size=20):
    """ 指定された座標周辺での画像間の変化を検出する関数 """
    diff = cv2.absdiff(image1, image2)
    _, thresh = cv2.threshold(diff, threshold, 255, cv2.THRESH_BINARY)
    changes_detected = False

    for pt in points:
        x, y = pt
        # 指定された座標周辺の画像領域を切り出す
        roi = thresh[max(0, y - area_size):y + area_size, max(0, x - area_size):x + area_size]
        # 領域内で変化があれば、フラグを設定
        if cv2.countNonZero(roi) > 0:
            changes_detected = True
            break

    return changes_detected

def click_event(event, x, y, flags, params):
    """ マウスクリックイベントのコールバック関数 """
    if event == cv2.EVENT_LBUTTONDOWN:
        points.append((x, y))
        print(f"Selected Point: ({x}, {y})")

# 座標を保存するリスト
points = []

# カメラからのフィードをキャプチャ
cap = cv2.VideoCapture(0)
cv2.namedWindow("Camera Feed")
cv2.setMouseCallback("Camera Feed", click_event)

ret, last_frame = cap.read()
last_frame = preprocess_image(last_frame)
last_check = time.time()

while True:
    ret, frame = cap.read()
    if not ret:
        break

    processed_frame = preprocess_image(frame)
    if time.time() - last_check > 60 and points:
        if detect_changes(last_frame, processed_frame, points):
            print("Change detected at specified points!")
        last_check = time.time()

    last_frame = processed_frame

    # 'q'を押してウィンドウを閉じる
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

    cv2.imshow("Camera Feed", frame)

# カメラリリースとウィンドウ破棄
cap.release()
cv2.destroyAllWindows()
tailwind-variantsで特定の条件の時にスタイルを変えたい場合の書き方

少し前からTailwindCSSを利用した開発を行なっています。
その中で条件に応じてスタイルを変えたい場合の記述方法についてです！

## tailwind-variantsの使い方

プロジェクトにインストールします。

```javascript
yarn add tailwind-variants
```

インストールできたらコンポーネントで呼び出します。
```javascript
import { tv } from 'tailwind-variants'
```

基本的な書き方は別の記事で紹介しているので割愛します！

https://qiita.com/tanimoto-hikari/private/3b2ccc23afd7ab9cd264

## tailwind-variantsで条件つきのスタイル定義
次のコードの例では`nested`がtrueの時にlistItemのテキストカラーとmarginを変更したいと思います。

```javascript
const list = tv({
  base: 'ml-7',
  variants: {
    nested: {
      true: 'text-red-700',
    },
  },
  compoundVariants: [
    {
      nested: true,
      class: 'ml-5',
    },
  ],
});
```

nestedがfalseだと下記の状態になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/7444793c-298e-523b-837e-c00dbbc5d197.png)

nestedをtrueの状態にすると**文字が赤くなり、marginのプロパティとしてml-5が設定**されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/8b0fe04f-8399-a1b8-78cc-5470b9635b88.png)

## まとめ
今回は単一条件によるスタイルの変更でしたが、2つ以上の条件でも設定することが可能です。

:::note warn
複雑すぎる定義するとコードの見通しが悪くなる可能性は高いです…
:::

　ただ、tailwind-variantsを利用することでシンプルに記述することもできるので導入の検討してみてください！
Pythonの並行処理と並列処理（非同期処理も）

# 目的
Pythonで処理の効率化を図ろうとすると、「逐次処理」「並列処理」「並行処理」「非同期処理」などの言葉を見かけると思います。

ここでは改めてそれぞれがどのように処理を行うのか、イメージや実装例をもとに学習することを目的としています。

# 前提知識
- コア
    - CPU内にある実際にプログラムの処理を行う部分
- プロセス
    - 実行中のプログラム
    - プロセス間はそれぞれ独立したメモリ領域をもつため、データの共有には向かない
- スレッド
    - プロセス内の処理で、CPUコアが処理する単位
    - CPUコア数 ＝ 同時実行できるスレッド数
    - 1プロセス内に最低1スレッドがあります。

以下は「マルチコア」「マルチプロセス」「マルチスレッド」のイメージ図になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621838/9cda96e9-d73d-997a-af16-52eae6f4157f.png)


# 複数タスクを処理するときの各処理の概要
## 逐次処理
**1人が複数のタスクを1つずつ処理**していくイメージです。
「シングルコア」「シングルスレッド」で処理を行う場合はこれに該当します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621838/1226e1ed-c466-e7aa-dcf6-568da205e0d3.png)

## 並行処理
**1人が複数のタスクを同時に処理**していくイメージです。
「マルチスレッド」で処理を行う場合にはこれに該当します。
また、同時に処理といっても、1人しかいないため瞬間的にみると処理しているタスクは1つとるため、「シングルコア」でも利用可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621838/82af10b0-ff52-ee09-faf1-425dc0984bc6.png)

## 並列処理
**風数人が複数のタスクをそれぞれ同時に処理**していくイメージです。
並行処理と違い、どの瞬間を切り取っても複数タスクを同時に処理できています。
「マルチコア」「マルチプロセス」で処理を行う場合はこれに該当します。
逆に「シングルコア」で並列処理を行ったとしても、1つのコアではタスクが交互に実行されるだけで実質並列処理と同等になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621838/08b5c528-1336-d552-2cbe-f0894c751b6c.png)

# 並行処理と並列処理の使い分け
### 並行処理
Pythonの並行処理は複数のタスクを高速に切り替えて処理を実行しています。
そのため、I/O操作が多い処理に向いています。並行処理を実装することで、I/O待機などの時間を他タスクに切り替えるなど、効率化を図れます。

:::note info
**I/Oバウンドな処理に最適**
データベース操作、ファイルシステム操作、WebAPIの利用などネットワーク通信を伴う操作などなど待ち時間が発生する処理に有効
:::

### 並列処理
Pythonの並列処理は各CPUコアが異なるタスクを同時に実行します。
そのため、CPUの計算能力に依存する処理に向いています。
ただし、プロセスごとに独立したメモリ空間を持つため、プロセス間でのデータの共有には注意が必要です。

:::note info
**CPUバウンドな処理に最適**
科学計算や画像・動画処理、暗号解読やデータ分析などなどCPU依存の処理に有効
:::

:::note warn
**並行処理でCPUバウンドなタスクを処理した場合のGILの問題**
PythonにはGIL（Global Interpreter Lock）と呼ばれるメモリ管理がマルチスレッドによる同時アクセスから保護するシステムがある。
これにより、CPUコアは一度に一つのスレッドだけが実行可能という制限がかかる。
I/Oバウンドなタスクであれば、並行処理でもI/O待機中はGILが解放され、他スレッドに処理が切り替わるためGILは悪影響を及ぼさないが、
CPUバウンドなタスクの場合、GILがスレッド間で頻繁に切り替わるため、並行処理のマルチスレッドの効果が低下してしまう。

GILのロック機構はプロセス間で独立しているため、CPUバウンドのタスクの場合はマルチプロセスを扱える並列処理を使うようにする。
:::

# 実装例
coming soon...

# 非同期処理（asyncio）
coming soon...
位置データにかわいいアイコンを表示したくなったら読む話。

昨日の続きです。

https://qiita.com/mountaincat/items/b829b382e212d192721a

さぁ、温暖な広島県でホワイトクリスマスを迎えることは出来るのか？？？

結論から、どん！

[TableauPublic:広島県でホワイトクリスマスは体験できるのか？](https://public.tableau.com/app/profile/.81026531/viz/_17016342090790/sheet2)

見られる・・・？かも？

100年平均で驚きの6か所？？！

いや、北広島とか八幡とか結構な豪雪地帯なんやけど、その日だけ特異的に降らないんか？？？
積雪はあるんですけどねぇ。

てなわけで、かわいいアイコンで地図を彩りたくなったらこうしようの記事です。

まず、今回はクリスマスの降雪がテーマなので雪だるまアイコンをとってきます。

https://icooon-mono.com/14255-%e9%9b%aa%e3%81%a0%e3%82%8b%e3%81%be%e3%82%a2%e3%82%a4%e3%82%b3%e3%83%b36/

ICOOON-monoさん、いつもお世話になっとります！

Tableauのダッシュボードで自分のテーマ色を決めている人は、色指定してダウンロードするといいですよ。

で、これをこのフォルダに保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/ef023219-364f-5c4d-9f08-8b28da688851.png)

※会社のPCなんかでローカルの標準外ファイルを全消しする仕組みになっている場合、まぁ、いい感じに調整してくださいな。

あとは、TableauPublicの画面から、以下の手順でアイコンを読み取れば使えます。

1. マークを形状に。
1. 形状の中からその他の形状を選択
1. 形状パレットのプルダウンからカスタムを選択
1. 使いたいアイコンをクリック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/64e052e8-86c8-d10b-fee8-aca3c6ffa188.png)


あとは、昨日作ったデータを読み込ませて地図描画して降雪量のデータを形状にもってくればOK！
気象観測所の場所はマイナーな地名や他の都道府県の地名を重複することもあるので、必ず緯度経度の情報を地理的情報に指定して地図描画に使ってね、北広島とか北海道にもある罠。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/8c2fd4ca-6a9b-3e09-a158-262de4c0546e.png)




ちなみにデータの工夫次第でこんなお遊びも出来ます。
押し寄せる雪だるま・・・。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1167883/5b00a91e-1a1c-e4c1-de6b-bab95261524c.png)
正しいHTML要素を使おう！

## 始めに
この記事は[群馬高専 Advent Calendar 2023](https://adventar.org/calendars/8705) 5日目の記事です

## HTMLとは
HTML(HyperText Markup Language)とは、ざっくり説明すると、Webページを記述する際に用いられるマークアップ言語の一つです。HTMLにはタグと呼ばれる構文があり、  

* `<h1>`や`<div>`などの開始タグ
* `</h1>`や`</div>`などの終了タグ

を用いて書いていきます。
同じ開始タグと終了タグで文字列などを囲んだ全体を要素といいます。
また、タグで他の要素を囲むこともでき、使うタグ（用いる要素）の種類で **特定の構造を表す要素** を書くことができます。

### 例
```html
<h1>見出し１</h1>
```
このとき  
`<h1>`は h1 の開始タグ  
`</h1>`は h1 の終了タグ  
`<h1>見出し１</h1>`は h1要素 を表します。

:::note info
HTML要素には空要素と呼ばれる、内容を持たない要素があり、その要素は開始タグのみで1つの要素を表します。
```html
<img src="https://example.com/assets/example.png" alt="画像の例">
```

`src="..."`や`alt="..."`などは「属性」というものでその要素に情報を追加するものですが、この記事では割愛させていただきます。
:::

## 使うHTML要素の種類による注意点
さて、HTMLでは構文に沿って記述することで構造を書いていきますが、こんな注意点があります。

### とりあえずdiv要素
div要素は複数の要素を含めることで、それらをグループとする構造にします。
ただし、div要素は汎用的なHTML要素なので、 **特定の意味を持たないグループにのみ** 使用します。

:::note info
以下のように、ただ複数の要素をまとめるだけの場合はdiv要素を使うことができます。
```html
<div>
    <img src="https://example.com/assets/example.png" alt="画像の例">
    <p>この画像は例です。</p>
</div>
```
:::

:::note warn 
ただし、以下のように要素がヘッダーに位置しているなど、意味を持ったグループに属する場合にはheader要素など適したHTML要素を使用しましょう。
```html
<header>
    <img src="https://example.com/assets/example.png" alt="画像の例">
    <h1>ページのタイトル</h1>
</header>
```
:::

https://magazine.techacademy.jp/magazine/28724

### 太字にstrong要素
HTML要素には内容のテキストに装飾を加えるものがあり、代表的なものにstrong要素というものがあります。strong要素に囲まれたテキストは **強調され** 、太字になります。

```html
<strong>太字で強調するよ</strong>
```
 **結果** 
<strong>太字で強調するよ</strong>

また、似た要素にb要素というものもあり、b要素も内容テキストを太字にします。

```html
<b>太字だよ</b>
```
 **結果** 
<b>太字だよ</b>

どちらもテキストを太字にすることができますが違いは何でしょうか？
それは **意味合い的に強調しているか** です。
strong要素は強調することを目的としたHTML要素ですが、b要素はテキストを太字にするという装飾面での目的を持ちます。
ただし、装飾は「CSS」という言語でも記述することができるので、使う場合はstrong要素にするなど、統一することを心掛けておくと良いでしょう。

## さいごに
まだ書き足りない部分があったり、拙い文章だったりしますが、使うHTML要素に少し気を付けるとより良いHTMLページが書けるかも？
次は、莉奈恋さんの「最近読んで面白かった本と微妙だった本」です！
zsh-abbrは要らないかもしれない

abbrは素晴らしい。しかしプラグインを入れずとも簡単な設定でその基本機能を実現できる。人によってはこれで十分かもしれない。

# 1. _expand_aliasウィジェットを使う方法
zshには標準で`_expand_alias`というウィジェットが存在するので、スペースをタイプしたときこれを呼ぶようにする。

```zsh
bindkey    ' '    expand-alias-and-self-insert

expand-alias-and-self-insert() {
  local words=(${(z)LBUFFER})
  local word="${words[1]}"
  # カーソル前の単語がバックスラッシュで始まる場合は除外。ls等は除外
  if [[ ${words[-1][1]} != '\' && "$word" != "ls" && "$word" != "ll" ]]; then
    zle _expand_alias
  fi
  zle self-insert
}
zle -N expand-alias-and-self-insert
```

# 2. LBUFFERを書き換える方法
元ネタは[zsh wiki](https://web.archive.org/web/20180329223229/https://zshwiki.org/home/examples/zleiab)
こちらはaliasでなく`$abbreviations`という連想配列で定義する。

```zsh
setopt extendedglob

typeset -Ag abbreviations
abbreviations=(
  "Im"    "| more"
  "Ia"    "| awk"
  "Ig"    "| grep"
  "Ieg"   "| egrep"
  "Iag"   "| agrep"
  "Igr"   "| groff -s -p -t -e -Tlatin1 -mandoc"
  "Ip"    "| $PAGER"
  "Ih"    "| head"
  "Ik"    "| keep"
  "It"    "| tail"
  "Is"    "| sort"
  "Iv"    "| ${VISUAL:-${EDITOR}}"
  "Iw"    "| wc"
  "Ix"    "| xargs"
)

magic-abbrev-expand() {
    local MATCH
    LBUFFER=${LBUFFER%%(#m)[_a-zA-Z0-9]#}
    LBUFFER+=${abbreviations[$MATCH]:-$MATCH}
    zle self-insert
}

no-magic-abbrev-expand() {
  LBUFFER+=' '
}

zle -N magic-abbrev-expand
zle -N no-magic-abbrev-expand
bindkey " " magic-abbrev-expand
bindkey "^x " no-magic-abbrev-expand
bindkey -M isearch " " self-insert
```
Amazon Bedrockを知る③　e-ラーニング（AWS Skill Builder）

本記事は [Amazon Bedrock Advent Calendar 2023 by ナレコム](https://qiita.com/advent-calendar/2023/bedrock-knowledgecommunication) の6日目の記事です。

Amazon Bedrock Advent Calendar 2023 by ナレコム ではAmazon Bedrockの基本的な概要から具体的な各モデルの作り方や事例紹介などを行っていきます。

### はじめに
AWS Skill Builderで提供されているAmazon Bedrockの学習コースは、Amazonの最先端の基盤モデル（FMs）と、生成AIアプリケーションを迅速に構築・拡大するためのツールセットを提供する完全管理型サービスです。このコースでは、Amazon Bedrockの利点、機能、一般的な使用事例、技術的な概念、そしてコストについて学ぶことができます。


### コースにアクセスする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/1aa34fa7-eea0-fd71-a96a-12a18855a754.png)

AWSコンソールからAmazon Bedrockにアクセスし、Overview（概要）ページの下部にあります。

３つある「Your Amazon Bedrock learning journey」の右側にある **Learning course** からアクセス可能です。

コースはAWS Skill Builderで提供されており、利用するにはアカウント登録して「AWSビルダーID」が必要となります。なお、Amazon Bedrockのコースは無料で提供されております。


### コース内容
- **コースレベル**: 基本
- **期間**: 1時間
- **活動内容**: プレゼンテーション、グラフィックス、ステップバイステップのチュートリアル

### 学習目標
このコースでは以下を学びます：
- Amazon Bedrockの仕組みを理解する。
- Amazon Bedrockの基本概念に慣れる。
- Amazon Bedrockの利点を認識する。
- Amazon Bedrockの典型的な使用事例を挙げる。
- Amazon Bedrockソリューションに関連する典型的なアーキテクチャを説明する。
- Amazon Bedrockのコスト構造を理解する。
- AWS管理コンソールでのAmazon Bedrockのデモを実装する。

### 前提条件
- **推奨トレーニング**: AWS Technical Essentials

### コース概要
1. **Amazon Bedrockの紹介**
2. **アーキテクチャと使用事例**
3. **Amazon Bedrockの使用方法**
4. **さらに学ぶ**

このコースは、Amazon Bedrockを活用したチャットボットソリューションの構築例を含むアーキテクチャを検討し、段階的な指示、およびトランスクリプトを含むガイド付きチュートリアルを通じて、AWSアカウントでAmazon Bedrockを試す機会を提供します。


### まとめ
本コースは2023年12月現在、日本語はなく英語・中国語・スペイン語などで提供されております。
ただし、本コースは文字を選択することも可能で、Google翻訳などでページ上で翻訳するか、翻訳サイトで翻訳することができます。また、ボリュームも1時間を想定している内容となっており、それほど時間をかけずに網羅的にAmazon Bedrockを学ぶことができます。

---

また、ナレッジコミュニケーションでは  **「[Musubite](https://recruiting.musubite-job.com/features/company/knowledge-communication)」** というエンジニア同士のカジュアルトークサービスを利用しています！この記事にあるような生成AI 技術を使ったプロジェクトに携わるメンバーと直接話せるサービスですので興味がある方は是非利用を検討してください！

https://recruiting.musubite-job.com/features/company/knowledge-communication
「ヘルシープログラマ」を読んだので、その感想

「ヘルシープログラマ」。オライリーより。

https://www.oreilly.co.jp/books/9784873117287/

![](https://m.media-amazon.com/images/I/81SlFv0Vl6L._SY466_.jpg)

> 長時間座ったまま仕事を続けるプログラマには、腰痛、手首の痛み、目の痛みや頭痛がつきものです。少しの間イスから立ち上がったり、食生活を意識したり、体重などの数値を計測するなど、生活習慣を変えるだけで健康状態は改善します。 本書は、身体を意識することの重要性やウォーキングが健康に及ぼす好影響、栄養を意識した食事、簡単なエクササイズを解説し、さらに眼精疲労や腰痛など、プログラマが直面する様々な健康問題を回避し克服するアイデアとテクニックを紹介します。日本語版では吉岡弘隆氏による「散歩とイングレス」を付録として収録。プログラミングを快適に続けたいと考える技術者必携の一冊です。


という一冊です。

## 感想

- 「本書を読むべき最大の理由は、あなたの生活がそこにかかっているからです。ただし、2番目に重要な理由として、あなたのキャリアがそこにかかっているということもあります。プログラマという愛する仕事をこの先何年も続けたいと思っているなら、本書を読んでみてください。」
- 目次が熱い
    - 1.1　健康のユニットテスト
    - 1.2　精神と身体のつながり
    - 1.3　健康へのイテレーティブなアプローチ
    - 1.4　習慣の背景にある科学
    - 1.5　習慣の再プログラミング
- 新しいことを学ぶ前後にエクササイズをすることで、その内容を記憶しやすくなる
    - 今すぐ散歩してみましょう。本書を置いて、歩き回ってみて、血流を活発にしましょう。5分から10分ほどしたら、戻ってきて中断した部分を読み直してみてください。あなたの思考、記憶、集中の能力は、脳に血液が戻ってきたことによって拡張されているでしょう。実際に、いくつもの科学的研究によって、この種のエクササイズが新しいことを学ぶ能力に直接的なインパクトを持つことが示されています
        - 運動をしっかり初めて以来、確かにこれを感じていた。単に筋力が増えるとか持久力が増えるとか以前に、運動している間に良く頭がさえたりアイディアが浮かんだりうまく記憶が定着したりして仕事にメリットになると気づいた。
- 歩数計を買う、安静時心拍数を知る
    - Fitbit を格好つけに買ったが正しかった
- PC スタンド的なものを買った方がいいのかもしれない
    - https://www.amazon.co.jp/dp/B0845RFFHN
    - https://www.amazon.co.jp/dp/B08BC3LF4L
- 「意識的に食べるためのフローチャート」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/35c9f3df-e04c-b7d4-d52c-e224381463c1.png)
- 腰痛、頭痛、目の痛み なんだな
- 腰痛対策
> - ミーティングや電話中は立つようにする
> - 休憩の間は立つようにする
> - 昼食時に散歩する
ウォーキングのメリットは否定の余地がないものであり、この議論に最も関係するメリットは、ウォーキングは腰痛を減らすための役に立つということです。
- 「椅子を離れるのに最もいい方法の1つは、コードを書く必要がない時には立ち上がるようにすることです。ミーティングの間は立ち上がる習慣をつけましょう。そうしておけば、目を覚ましておくことだって簡単だと分かるかもしれません！」



## まとめ

書いてあることは結局いかに運動するか、良い食事をとるか等々である。が、「そうは言ってもコードを書かないといけない、座らないと作業が進まない」あるいは逆に「立つ必然性がなかなかない」、我々の職業の中における悩みに特化した解決策が書かれている点で有意義な本だと思う。



以上です～

つづく。
symbol-bootstrapの7900ポートを変更する

## はじめに

ネットワーク内に複数ノードを設置する場合、catapult サーバーポートが重複してしまい、片方のノードだけ外から見える状態になってしまいます。外から見えない方のノードのピア数が減少して(接続できないので周りのノードから Ban されます)、ちょこっとだけフォーク耐性が下がります。

というわけで、デフォルトの`7900`ポートから別のポートに変更して、各ノードちゃんと通信出来るようにしましょう。

:::note warn
同じマシンに複数台ノードをインストールするのは、コンテナ名の重複等あるので追加で設定が必要です。それはまたの機会に…
:::

## カスタムプリセット変更

カスタムプリセットに`nodePort`、`apiNodePort`を追加します。ポート番号は使用していない番号を適当に設定してください。  
私は`7911`にしました。

```my-preset.yml
nodePort: 7911
apiNodePort: 7911

nodes:
    -
        host: symbol01.harvestasya.com
        friendlyName: _Symbol_HarvestasyaNode01/.
```

## docker-compose.yml 変更

`docker-compose.yml`まで変更するコマンド的なものは存在してないようなので、手動で node コンテナのポートを変更します。`7900`となってるところを`7911`に書き換えます。

```target/docker/docker-compose.yml
    node:
        user: '1001:998'
        container_name: node
        image: symbolplatform/symbol-server:gcc-1.0.3.6
        command: /bin/bash /symbol-commands/start.sh /usr/catapult ./data server broker node NORMAL true
        stop_signal: SIGINT
        working_dir: /symbol-workdir
        restart: on-failure:2
        ports:
            - '7911:7911'
        volumes:
            - ../nodes/node:/symbol-workdir:rw
            - ./server:/symbol-commands:ro
        depends_on:
            - db
            - broker
        networks:
            default:
                aliases:
                    - symbol01.harvestasya.com
        hostname: symbol01.harvestasya.com
```

## docker-compose.yml の変更を自動化

`symbol-bootstrap compose --upgrade`をしたら`docker-compose.yml`のポートを変える必要があるのですが、忘れるので私はバッチで一括で変更するようにしてます。

```symbolVersionUp.sh
#!/bin/bash

echo "preset更新"
symbol-bootstrap config -p mainnet -a dual -c my-preset.yml --upgrade

echo "compose更新"
symbol-bootstrap compose --upgrade

echo "composeポート変更"
sed -i s/7900:7900/7911:7911/ target/docker/docker-compose.yml
```

## さいごに

これで、同じネットワーク上に複数台のノードがあっても上手く通信出来るようになりました。  
同ネットワーク上にサーバー複数台ってそうそう居ない気もしますが…うちはあるんですよ！

そうそう、リバースプロキシってのがありますね。これで上手く振り分けられないかと考えたんですが、この 7900 はソケット通信なのでホスト名使ってるのか謎なので出来るか不明です。
土台は作っているのですが、ノード 2 つ余裕で動くマシンが必要なので確認に手が出てないです…
2023/12/5主にITとかセキュリティの記事

［社説］LINEヤフーに猛省求める(12/3)
https://www.nikkei.com/article/DGXZQODK0242M0S3A201C2000000/

さまざまなデータ分析エンジニアが目撃したこれまでで最悪の失敗は？(12/3)
https://gigazine.net/news/20231203-worst-data-engineering-mistake/

セキュリティ周りでよく見かける単語についてまとめ（XSS,CSRF,CSP）(12/2)
https://qiita.com/Terufuji3/items/45f56468152706e2e828

京都府警などが「ウェブスキミング」初摘発、通販サイトからカード情報窃取(12/3)
https://www.fashionsnap.com/article/2023-12-03/web-skimming/

被害額580億円相当…「暗号資産」を盗んだ犯人はどう追跡されるのか？サイバー犯罪の現状(12/2)
https://gentosha-go.com/articles/-/56342

Windows 10のサポート終了が見えた！Windows 11にアップデートしていない人が注意すべきポイント(12/3)
https://dime.jp/genre/1696039/

広島大学病院　電子カルテシステム障害が復旧　４日から通常通り診療(12/2)
https://www.fnn.jp/articles/-/624359

習近平氏の家族の個人情報をネットに公開し、懲役14年判決の男性　刑務所で暴行を受け精神に変調、母親は早期仮釈放を要求(12/3)
https://news.infoseek.co.jp/article/postseven_1924740/?tpgnr=world

台湾総統選、水面下で〝中国介入〟か　野党候補の一本化工作、スキャンダルからサイバー攻撃による得票操作と…何でもあり(12/3)
https://www.zakzak.co.jp/article/20231203-QWBF3W3SP5IDHEZHWWR5GEA72M/

ランサム被害でログまで暗号化　約3日で復旧も感染経路特定できず(12/4)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600011/112900145/

さよならパスワード　導入進む「パスキー」(12/4)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600014/112400162/

SSIDでは見抜けない「悪魔の双子」の偽Wi-Fi、実は危険な自動接続(12/4)
https://xtech.nikkei.com/atcl/nxt/column/18/02635/110700002/

「IT需要の抑制」が必要だ　空前の技術者不足への処方箋(12/4)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600007/112800155/

Catena-X(12/4)
https://xtech.nikkei.com/atcl/nxt/mag/nc/18/020600009/112800156/

Wi-Fi 6Eの電波は届きにくい？(12/4)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/031600159/111600009/

イーサネット 有線LANを実現する伝送技術の「標準」(12/4)
https://xtech.nikkei.com/atcl/nxt/mag/nnw/18/091900172/111600003/
Azure上でGPT-4-Turboを使う方法

本記事は [OpenAI活用法 Advent Calendar 2023 by ナレコム](https://qiita.com/advent-calendar/2023/openai-knowledgecommunication) の4日目の記事です。

OpenAI活用法 Advent Calendar 2023 by ナレコム ではGPTsを含めた最新のOpenAIの活用法について紹介します。

### はじめに

Azure上でも **GPT-4-Turbo** が利用できるようになりました。
限られたリージョンでしか提供されておらず、有効化するためには提供されているリージョンを探す必要があります。本記事では、リージョンの選び方と有効化の方法を紹介します。

### **GPT-4-Turbo** が利用できるリージョンの探し方

1. [Azure OpenAI Studio](https://oai.azure.com/) にアクセス
1. 左メニューの「管理」から **「クォータ」** を選択します。
1. 以下のような画面が表示されるのでリージョンを変更し、**GPT-4-Turbo** が表示されるリージョンを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/2f224f0e-ef7b-5b3c-6e3a-a6c2ca9820ef.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/f9c32582-fa0b-8791-1431-ab3b8ba87bd1.png)

:::note info
GPT-4-Turbo 以外にも限られたリージョンで提供されているモデルとして以下がありました
- whisper
- DALL-E
:::

### **GPT-4-Turbo** の有効化方法

1. Azure OpenAI Serviceインスタンスの作成
AzureポータルからAzure OpenAIを選び、前述の方法で **GPT-4-Turbo** が確認できたリージョンを選択してインスタンスを作成します。
1. [Azure OpenAI Studio](https://oai.azure.com/) にアクセスし、左メニューから「デプロイ」に選択する
1. 「＋新しいデプロイの作成」をクリックして以下のようにして作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/61189/f9d85e92-aade-f175-6df7-d047116c8275.png)
※GPT-4-Turboは直接選ぶのではなく、GPT-4の中の **1106-Preview** を選択することで有効にできます。

### まとめ

いかがでしたでしょうか？
今回は **GPT-4-Turbo** の有効方法ですが、同様の方法で **whisper** や **DALL-E** を有効にすることができます。おそらく今後も新しいモデルについてはこの方法で利用できるものと思われます。

---

また、ナレッジコミュニケーションでは  **「[Musubite](https://recruiting.musubite-job.com/features/company/knowledge-communication)」** というエンジニア同士のカジュアルトークサービスを利用しています！この記事にあるような生成AI 技術を使ったプロジェクトに携わるメンバーと直接話せるサービスですので興味がある方は是非利用を検討してください！

https://recruiting.musubite-job.com/features/company/knowledge-communication
[Firebase] Firestoreの集約クエリ (count, sum, average) について

Firestoreの集約クエリ (aggregation queries)　を使用すると、複数のドキュメントの統計的な操作が簡単に行えます。
具体的には以下の3種類のクエリがあります。

- count
- sum
- average

公式ドキュメントではSwiftでのFirestoreのcountクエリの使い方についての説明がありましたが、sumやaverageに関する具体的なSwiftでの実装例は見つかりませんでした。そこで、この記事ではこれら3つのクエリ（count、sum、average）をSwiftでどのように使うかについて解説していきたいと思います。

また、料金的なメリットもありますので、それについても解説していきます。

# 実装方法
説明するにあたって、このような構造のコレクションがあるとします。
```yaml
- users # (Collection)
    - user1 # (Document ID)
        - name: "Mike"
        - age: 10
    - user2
        - name: "Takeshi"
        - age: 21
    - user3
        - name: "Taro"
        - age: 20
```

## count
countクエリではコレクションまたはクエリ内のドキュメントの数を取得することができます。
以下の例は20歳以上のユーザー数を取得するコードです。
```Swift
let count = try await Firestore.firestore()
    .collection("users")
    .whereField("age", isGreaterThanOrEqualTo: 20)
    .count
    .getAggregation(source: .server)
    .count
    .intValue
print(count) // 2
```

## sum
sumクエリでは、コレクションまたはクエリ内の特定のfieldの合計値を取得することができます。
以下の例は全てのユーザーの歳を足して、その結果を取得するコードになっています。

```Swift
let sum = try await Firestore.firestore()
    .collection("posts")
    .aggregate([.sum("age")])
    .getAggregation(source: .server)
    .get(.sum("age")) as? Int
print(sum) // Optional(51)
```

## average
averageクエリでは、コレクションまたはクエリ内の特定のfieldの平均値を取得することができます。
以下の例はユーザーの平均年齢を取得するコードになっています。

```Swift
let averageAge = try await Firestore.firestore()
    .collection("posts")
    .aggregate([.average("age")])
    .getAggregation(source: .server)
    .get(.average("age")) as? Double
print(averageAge) // Optional(17)
```

また、複数のfieldに対して集約クエリを実行することも可能です。
```Swift
let aggregateQuerySnapshot = try await Firestore.firestore()
    .collection("posts")
    .aggregate([.average("age"), .sum("age")])
    .getAggregation(source: .server)

let sumAge = aggregateQuerySnapshot.get(.sum("age")) as? Int
let averageAge = aggregateQuerySnapshot.get(.average("age")) as? Double

print(sumAge) // Optional(51)
print(averageAge) // Optional(17)
```

# 料金的なメリット
通常、Firestoreは読み取り・書き込み・削除を行うドキュメントの**数**に対して課金されます。
なので、1000個のドキュメントを読み取ったら1000回分の課金がなされます。

一方、集約クエリの場合は1000個のドキュメントにつき1回のドキュメント読み取り料金が発生します。
これにより、大幅な費用の削減を行うことができます。

しかし、集約する対象のドキュメントが1件であっても1回のドキュメント読み取り量が発生しますので注意してください。

# 参考

https://firebase.google.com/docs/firestore/query-data/aggregation-queries?hl=ja

https://firebase.google.com/docs/firestore/pricing?hl=ja
アルペジエーターを JavaScript で扱えそうな方法を調べてみる【完走賞ゲット-7】

 :::note info
※ [Qiita の完走賞をゲットするための条件は「単一／複数のカレンダーに投稿した記事が合計25」です](https://twitter.com/Qiita/status/1593441648796524545)
:::

この記事は、「[完走賞ゲットのため小ネタ 25記事を投稿しようとチャレンジ v2 Advent Calendar 2023](https://qiita.com/advent-calendar/2023/youtoy)」の 7日目の記事です。

## 今回の内容
今回の記事の内容は、「アルペジエーター」について調べてみたという記事です。

アルペジエーターを知ったきっかけは、以下の作品でした。

https://protopedia.net/prototype/4918

このユニークな楽器に関するデモを見ていて、ボタンが押された時に、良い感じの音を奏でている仕組みが気になりました。それについて作者の方から仕組みを聞いたところ、「アルペジエーター」を使っているという話を知りました。

そして思ったのが「プログラミングとアルペジエーターを組み合わせられないか」ということでした（※ この時点だと、アルペジエーターが何かというのは、詳しく分かっていなかったのですが）。

### アルペジエーターを検索してみる
まず、自分が「アルペジエーター」のことを知らないため、Google検索をしてみました。

●アルペジエーター - Google 検索
　https://www.google.com/search?q=%E3%82%A2%E3%83%AB%E3%83%9A%E3%82%B8%E3%82%A8%E3%83%BC%E3%82%BF%E3%83%BC

そして、検索結果のトップに出てきた以下のページを見て、「鍵盤を押さえるだけで、アルペジオ(分散和音)や、さまざまなパターンが自動的に再生される機能」という内容だと分かりました。

●アルペジエーターを使って演奏する CASIO MUSIC SPACE - Support - CASIO
　https://web.casio.com/app/ja/music_space/manual/WBSPSYfcdiyazk.html

なんとなくイメージがつかめた気がしたところで、プログラミングとの組み合わせという話に入っていきます。

### アルペジエーターをプログラミングで扱う（JavaScript を使う）
#### 「アルペジエーター JavaScript」で検索
「アルペジエーター」というキーワードに「[JavaScript」を足して検索](https://www.google.com/search?q=%E3%82%A2%E3%83%AB%E3%83%9A%E3%82%B8%E3%82%A8%E3%83%BC%E3%82%BF%E3%83%BC+JavaScript)してみました。

「アルペジエーター JavaScript」で検索して出てきた結果から、気になったものを 1つ抜粋してみました。
以下の内容は Webサイト上でアルペジオを生成できるものという話でした。

●ブラウザinミュージック！ アルペジオを生成できるサイトが登場 | ギズモード・ジャパン
　https://www.gizmodo.jp/2016/07/codepen-music-browser.html
 
![ブラウザinミュージック](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/5bb097ee-27c9-592a-e211-abd7ffb56a23.png)

どうやら、以下の CodePen で公開されている作品の紹介記事のようでした。

●Musical Chord Progression Arpeggiator
　https://codepen.io/jak_e/full/qNrZyw

#### 「Arpeggiator JavaScript」の検索結果
今度は、[アルペジエーターを英語にして検索](https://www.google.com/search?q=%22Arpeggiator%22+%22JavaScript%22)してみました。

そうしたら、[以前使ってみて記事も書いたことがある「Tone.js」](https://qiita.com/search?q=tone.js+user%3Ayoutoy)を使った内容が出てきました。

●Arpeggiator · Tonejs/Tone.js Wiki
　https://github.com/Tonejs/Tone.js/wiki/Arpeggiator

ざっと見た感じだと、自分でパターンを作成するような方向のようでした。

#### 「Arpeggiator Magenta.js」の検索結果
その他、[過去に使って記事にしたことがある「Magenta.js」](https://qiita.com/search?sort=&q=Magenta.js+user%3Ayoutoy) との組み合わせでも検索してみました。

そうすると、[公式の「Demos — Community made」のページ](https://magenta.tensorflow.org/demos/community/)に掲載された、「Neural Arpeggiator」というものも出てきました。

![Neural Arpeggiator](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/ad38b9c8-3618-f597-b135-790e52f9710e.png)

●Connecting with Music Through Magenta.js
　https://magenta.tensorflow.org/blog/2018/05/03/connecting-with-magenta-js

触ってみた感じだと、これをうまく活用できれば面白そうだと思いました。

## おわりに
ダイビングの物理

ダイビングの物理

⚠記事の内容は私個人の見解であり，所属する学科組織またはサークルを代表するものではありません。

・はじめに
記法？がよくわからないので素材のままの文章ですけどご了承下さい。
ちなみに今は12/5の0:30です。
(なんだかコードっぽいのが出てきたけど気にしません)
そう。もう記事ができてなきゃいけないのです！
時間が無いので画像も貼りません！
頑張って書くのでよろしくお願いします！
というわけで本文へどうぞ。

・ダイビングについて
私はこのサークルの他に海BOUZというダイビングサークルに入っているのですが、何か書くことないかな〜と考えた時に「ダイビングって珍しいんじゃない？」と思ったので私がダイビングを始めたての頃に驚いたことを物理的視点からまとめます！

・減圧症
減圧症とは高圧環境下で血液や組織中に溶けていた窒素が、減圧に伴い気泡をつくる状態のことです。
減圧症のメカニズムはこうです。
1.水深の深いところに潜ったときに圧力が大きくなる
　P=P0+ρhgですね！
2.圧力に比例して血液中に溶ける窒素の量が増える
　これはヘンリーの法則ですね！高校化学でした覚えがあります。
3.水深の浅いところへ急浮上すると水圧が下がるので血液中の窒素が気泡になる
　血液中の気泡が悪さをして疲労感、筋肉や関節の痛み、しびれ、チクチク感、腕や脚の筋力低下、ふらつき、回転性めまい（目が回る）、呼吸困難、胸痛などいろいろな症状がでます。怖いですね。
減圧症にならないためにどうすればいいのか？
それは急浮上しないことと、安全な水深で数分間停止することです。
講習中にこれをしないと怒られます。
私は怒られました。
みなさんも気をつけましょう。

・浮上するときに空気を抜く
ダイビングではBCDという空気をいれて浮力を確保するライフジャケットのようなものを着るのですが、これに入っている空気の体積は水深によって増減します。
ここで問題です。
浮上するときにこのBCDに空気を入れるでしょうか、抜くでしょうか。
一見、浮上したいので空気をいれると思いますよね。
しかし！入れてはいけないのです！
それでは解説しますね。
水深が深いところから浅いところへ浮上するとと水圧が減るのでBCD内の空気の体積は増えます。
pV=nRTですね！気体の状態方程式です。
そして体積が増えるとあれが大きくなります。
そう、F=ρVg、浮力です。
浮力が大きくなると当然、浮上速度が大きくなります。
すると、そう！急浮上してしまいます！
さきほど説明した通り急浮上すると減圧症のリスクがあるのでBCDに空気を入れたまま深いところから浮上するのはよくありません。
なので浮上中は空気を抜きながらフィンでゆーっくり浮上するのです。
これもよく忘れます。
なのでよく怒られます。
ダイビングは最悪このことと次で説明することを覚えておけばまあ大丈夫です。

・息を止めてはいけない
ダイビング中は"絶対に"息を止めてはいけません。
なんだかとても強い言い方で怖いですがこれには理由があります。
肺には空気が入ってますよね。
もし浮上中に息を止めているとどうなるでしょうか。
ご明察の通り、肺の中の空気の体積が増えて、肺が破裂します。
最悪の場合、肺胞も破裂します。
こうなった場合、すぐに処置をしないと命を落としていまいます。
これは本当に強く言われます。
まあ同じ深度であれば止めても大丈夫ですが、初心者のときは呼吸を止めてはいけないという意識をもつことがすごく大事です。
みなさん、本当に気をつけましょう。

・おわりに
ただいまの時刻は2:30です。
ジョジョの奇妙な冒険第3部のアニメを友達の家で見ながら執筆していたのでそこそこ時間がかかってしまいました。
面白いですよね、ジョジョ。
そんなことはさておき。
日が回ったころはアドベントカレンダーを書こうとしたことを後悔していたのですがちょうどいい題材があったこともあり途中からは楽しかったです。
眠たいですけど。
さらに余談ですが昨日の人の記事に関連して一言。
私の勉強法は教科書の要点を抜き出した後、そのページをカッターで切り取ることです。
薄い教科書を見ると達成感を感じますよね。
おわり。
Next.js App Router：ESモジュール export 定義について

# はじめに

こんにちは！開志専門職大学大学 3 年(25卒)のかずや(@bearone236)と申します！
今回は、最近 version 14 から安定版として登場した Server Actionsや、Next.js Native が登場して世間では大盛り上がりを見せている **Next.js** に関しての投稿したいと思います。

内容は **「version13.4 から登場した App Router での Export の扱い方について」** です！

ブログ自体は非常に短いものとなっていますが、自分の失敗談から得た知識のため **備忘録** として残したいと思います。

ではいきましょう！！

# Next.js とは

[Next.js](https://nextjs.org/docs)とは、React のフレームワークであり、フルスタック Web アプリケーションを構築するためのツールとして登場し、話題を博しています。


Nextjs の記述は React をベースとしているため、React を学習している・開発している人にとっては非常に挑戦しやすいフレームワークとなっています。(ちなみに簡単ではないです。コッテリな内容となっています。)

-------------
React と異なる大きな特徴としては特に下記が挙げられます。

- version13.4 以前と以後によるルーティング設定の違い (Page Router と App Router)
- SSG, SSR, ISR など、レンダリング手法が複数存在しており、アプリケーションの特徴によってレンダリングを切り替えることができる

:::note
レンダリング手法の違いについてやルーティングについて、Next.js の歴史については学習量が膨大なため、気になる方は公式ドキュメントをご確認ください。 今後これらのトピックについてもブログとして発信していきたいと思います！
:::

# 該当バージョン

- Next.js： version13.4 から

# 発生した App Router での問題

app ディレクトリ配下に、`app/hoge/page.jsx` ファイルを作成しルーティング設定を行おうと考え、下記のコードのように関数を定義しました。

### 【問題点】

page.jsx ファイル ( **app/hoge/page.jsx** )

```jsx
// 関数宣言
export function Page() {}

// 関数式(アロー関数)
export const Page = () => {};
```

- 上記のように関数式、関数宣言それぞれで、ただのルーティング設定を行ったところ、下記のランタイムエラーが出力されました。

> **Unhandled Rutime Error**
> Error: The default export is not a React Component in page: “/hoge”

### 【解決方法】

- page ファイルの関数定義を`export`ではなく、 `export default` に変更

```jsx
// 関数宣言
export default function Page() {}

// 関数式(アロー関数)
export default const Page = () => {}
```

### 【上記の結果から自身で考えたこと】

- Default Export は **1 つのファイル(モジュール内)に 1 つだけ export することができるため「ファイルの責務を強制的に 1 つに絞ることができる」** という特徴を持っている。


- Default Export は **「別ファイルでの import 時に命名を変更することができる」** という特徴を持っている。
  → Next.js の App Router は、`page.jsx` ファイルによってルーティングファイルを判断しているため、export 時は **命名を変更できるように** `default export` で扱うような **「仕様」** が Next.js 内で存在するのではないか？

  ( **Next.js 側**：  「page.jsx ファイルだから、App Router の Page 関数宣言・関数式になるはず… だからインポート時に混在しないように export default で命名変更できるようにしよう！」 )

# 参考文献

https://nextjs.org/docs

https://nextjs.org/docs/app/building-your-application/routing

https://developer.mozilla.org/ja/docs/web/javascript/reference/statements/export

https://zenn.dev/yuji6523/articles/373a675275abc4
10年使えるパソコンを作りたい(エンジニア編)

# 概要

2023年7月に作った自作PCの構成を紹介します。


# 背景

今回は自宅の家族共用のWindows PCを自作しました。8年前に購入したノートPCを使っていましたが、Windows 10のサポート期限が近づいていることもあったのでWindows 11に早く変えたくなり、新しく作ることにしました。
エンジニア向けに開発にも使えるよう、少し強めの性能で組みました。


# 方針

- 私の使いたい部品を使いつつ、全体の値段はできる限り安く抑える。
- 10年快適に使えるパソコンを目指す。そのために少し性能の良い部品を選ぶ。
- Web閲覧や動画試聴、オフィスソフトに加え、開発用途でも快適に使えるようにするために少し強めの構成とする。


# 構成

## CPU

Intel Core i5 13400

https://kakaku.com/item/K0001506431/

Intel 13世代のCore i5 CPUです。Eコアを持つCPUを使ってみたかったので選びました。Intel 12世代のCore i5に続き13400も快適です。グラフィック機能付きモデルを選び、グラボなし構成とします。

別売CPUクーラーは使わず付属のリテールクーラーを使います。冷却性能・動作音とも問題無しです。


## マザーボード

ASRock B760M Pro RS/D4 WiFi (B760 1700 MicroATX) ドスパラ限定モデル

https://www.asrock.com/mb/Intel/B760M%20Pro%20RSD4%20WiFi/index.jp.asp

大きな拡張はしない予定なので、MicroATXを使うことで価格を抑えます。ミドルクラスチップセットB760の中で、Wifiが付いており、将来の拡張性を考慮してUSB-Cが付いているモデルを選びました。


## グラフィックボード

無し。その代わりに、グラフィック内蔵のCPUを選んでいます。

グラフィックボードが不要でシンプルな構成にでき、トラブルが起こった時の原因切り分けが楽になります。このグラフィック機能でもMinecraftは遊べます。


## メモリ

CFD W4U3200CS-16G (16GB×2枚組)

https://www.cfd.co.jp/consumer/product/detail/w4u3200cs-16g.html

開発やクリエイティブ用途で使うことも想定して多めに32GBとしました。
まだDDR5が高かったのでDDR4です。定格3200MHzのメモリを選んでいます。


## SSD

KIOXIA EXCERIA PLUS G2 (1TB)

https://www.kioxia.com/ja-jp/personal/ssd/exceria-plus-g2-nvme-ssd.html

10年先を考えて500GBで足りなくなる可能性を考えて1TBにしました。容量とコストのバランスも良かったです。


## 電源

玄人志向 KRPW-L5-400W/80+ (400W)

https://www.kuroutoshikou.com/product/detail/krpw-l5-400w-80-.html

前回と同様、定番を選びました。コスト重視です。
CPU補助電源のケーブルの流さがやや短かいため、今回のケースではギリギリでした。最終的に延長ケーブルを使いました。


## ケース

Thermaltake Versa H26

https://www.ask-corp.jp/products/thermaltake/middle-pccase/versa-h26.html

コスパ重視の定番ATXケースです。DVDドライブを使うため外付け5インチベイが使えることを必須で探しました。
片面がアクリル板となっており、中で光っている様子が分かります。


## ケースファン

Sirius Extreme ASE120

https://www.aiuto-jp.co.jp/products/product_3763.php

冷却観点ではケースに添付されているファン2個でも十分だと多いますが、中が見えるケースなので光るファンを追加しました。リングのみ光るタイプです。コスト重視です。


## OS

Microsoft Windows 11 HOME

10年サポートしてくれるのがベストですが、サポートが切れてしまったらLinuxなどを入れて使います。


# 値段

以上の合計で10万円弱(OS込み・当時の価格)でした。


# 感想

4カ月程使っていますが問題無く動いています。余裕を持ってCPU・メモリを選んでいるため快適です。
改善点があるとするとサイズがやや大きいことが気になっています。MicroATX向けの小さいケースに変更したいのですが、外付け5インチベイに対応したケースが少ないため選ぶのが難しいです。
私のSQLパフォーマンスチューニングのやり方

この記事は[アイスタイルAdvent Calendar 2023](https://qiita.com/advent-calendar/2023/istyle) 7日目の記事です。

アイスタイルでDBREを担当している@suzukitoです。
今年のアドベントカレンダーは、SQLパフォーマンスチューニングの話にする事にしました。

# 私のSQLパフォーマンスチューニングのやり方

一言でまとめると、

**「DBMSの気持ちになって考える」**

です。

DBMSの気持ちになってSQL文を解釈し、「ここがこうなってたらなぁ」と、彼が思っているであろうことを察してあげるのです。

# DBMSのお気持ち

彼はこんな気持ちでSQLを実行していると想像します。

- インデックスが無ければ、オレは愚直にフルスキャンをやるだけだぜ
- インデックスが無ければ、オレは愚直にソートをやるだけだぜ
- インデックスがあれば、検索やソートに利用するぜ
- SQL文を見て思うことはあるが、俺からは言えないんだよ。察してくれよな！

彼は愚直に指示通りに仕事をしてくれます。
でもSQLの実行を速くしたいなら、彼の気持ちを察して仕事が楽にできるようにしてあげる必要がありますね！

# DBMSのSQL実行手順

おおむね、このような順番で実行されます。

1. SQL文の構文解析をする
1. 実行者の権限を確認する
1. テーブル定義を確認する
1. インデックス定義を確認する
1. 統計情報でデータの概要を確認する
1. 複数の実行計画を作成してコスト計算する
1. 一番コストの低い実行計画を実行する

SQLのパフォーマンスチューニングをする時は、DBMSの気持ちになって、同じステップをなぞってみましょう。

## SQL文の構文解析をする

まずは、SQL文自体を確認します。
SQL文の構文解析をしているとき、彼はこう感じていることでしょう。

- WHEREの条件指定で列の方に関数を使ってると、インデックス使えないんだよなぁ
- LIKEで先頭に%使ってると、インデックス使えないんだよなぁ
- INの引数をSELECTでテーブルから取得するなら、JOINしてくれた方がありがたいんだけどなぁ
- SELECTの列にSELECT文書いてんのか、JOINしてくれた方がありがたいんだけどなぁ
- 最後にまとめてWHEREするより、JOINする時に指定してしてくれた方がI/Oが減るんだけどなぁ
- 最初っから結果を意識してJOINしたり列を選びすぎたりしすぎなんだよなぁ。まずは軸になるテーブルの主キー集合を見つけてくた方がI/Oが減るんだけどなぁ

などなど。お気持ちを察してSQL文を修正してあげましょう。


## テーブル定義を確認する

テーブル定義を確認するとき、彼はこう感じていることでしょう。

- この列はNOT NULLだから必ず値が入ってるな。やりやすいぜ
- この列はNULL許可か、、、面倒だけど、集計や比較で考慮せんとな
- この列intだったのか、WHEREで文字列と比較してるから型変換しないとだわ。インデックスが使えなくなるんだよね
- この列tinyintでチェック制約付きか。値の範囲が絞れるから助かるな
- この列には外部キー制約付いてるのか。てことは別のテーブルの主キーだな

などなど。察してSQL文を、可能であればテーブル定義を修正してあげましょう。


## インデックス定義を確認する

インデックス定義を確認するとき、彼はこう感じていることでしょう。

- WHEREの指定列にインデックスがないんか、フルスキャンだな
- JOINの結合列にインデックスがないんか、フルスキャンだな
- ORDER BYの指定列にインデックスがないんか、結果返す前にソートせんとだわ
- インデックスがあるのに比較するデータ型を間違えてるんか、、、残念！フルスキャン
- インデックスがあるのに列を関数で囲っちゃってるんか、、、残念！フルスキャン
- 値がユニークなら、ユニークインデックスで定義して欲しいわ。優先的に使うようにするからさ

などなど。インデックスがない＝フルスキャンです。
お気持ちを察してインデックスを作ってあげましょう。

主キー検索とユニークインデックス検索は最速のアクセス方法です。
インデックスの値がユニークかどうか判断できるのは設計者だけです。
ユニークで定義できるなら、積極的にユニークインデックスにしましょう。
判断材料になります。


## 統計情報でデータの分布を確認する

統計情報はテーブルやインデックスの行数、列の値の種類や分布を集計した情報です。
統計情報を確認するとき、彼はこう感じていることでしょう。

- カーディナリティが高いから、このインデックスは使えそうだ
- カーディナリティが高いけど、分布が偏ってるな。このSQLには向かないかも
- 2値しかない列が第1列に指定されてんのか、、、少ない方を見つける時にしか使えんな

などなど。SQLのパフォーマンスはデータの分布状況によっても変わります。
SQL文ばかり見てないで、データの確認もしてお気持ちを察してあげましょう。

# まとめ

人がSQLを書くときの観点と、DBMSがSQLを実行する時の観点は異なっています。
人が書くSQLは結果のデータを意識して書かれます。
そのSQLをDBMSが実行する時には、より少ない労力で処理することが意識されます。
DBMSの気持ちになって、DBMSが仕事をやりやすい環境を作ってさしあげて、SQLの速度改善に取り組んで行きましょう！


# 参考資料

- [SQLデータベースにおけるバランス検索木(Bツリー)](https://use-the-index-luke.com/ja/sql/anatomy/the-tree)
- [MySQL :: MySQL 8.0 リファレンスマニュアル :: 8 最適化](https://dev.mysql.com/doc/refman/8.0/ja/optimization.html)


# 他にも書いてます！

過去の投稿でDB関連の記事はこちら。

https://qiita.com/suzukito/items/edcd00e680186f2930a8

https://techblog.istyle.co.jp/archives/1514

https://qiita.com/suzukito/items/ca6a19fc7c6dec35b302

https://zenn.dev/istyle/articles/0b9cf1b2acd9f8

https://qiita.com/suzukito/items/60d3167ca63cdff7ad79