반응형

데이터베이스 설계에서 테이블의 컬럼 수는 성능과 관리 효율성에 큰 영향을 미칩니다. 특히 PostgreSQL과 같은 관계형 데이터베이스에서는 컬럼 수를 적절하게 제한하는 것이 중요합니다. 오늘은 PostgreSQL에서 권장되는 컬럼 수와 성능을 고려한 데이터베이스 설계 팁을 알아보겠습니다.

1. PostgreSQL의 컬럼 수 한계

PostgreSQL은 테이블 당 최대 1,600개의 컬럼을 허용합니다. 이론적으로는 많은 수의 컬럼을 포함할 수 있지만, 실무에서 이렇게 많은 컬럼을 가진 테이블을 설계하는 것은 좋지 않습니다. 너무 많은 컬럼은 성능 저하, 데이터 관리의 어려움 등을 초래할 수 있기 때문입니다.

2. 실무에서 권장되는 적정 컬럼 수

PostgreSQL에서 50개 이하의 컬럼이 가장 이상적인 수치입니다. 이는 유지보수성, 인덱스 관리, 쿼리 성능을 종합적으로 고려한 결과입니다. 실무에서는 테이블의 컬럼 수가 많아지면 관리가 어려워지고, 불필요한 데이터 전송이 많아져 쿼리 성능이 저하될 수 있습니다.

50개 이상 200개 이하의 컬럼은 특정 요구 사항에 따라 허용될 수 있지만, 200개 이상의 컬럼을 초과할 경우 성능 저하가 본격적으로 나타나므로 가능한 피하는 것이 좋습니다. 예를 들어, 너무 많은 컬럼이 포함된 테이블에서 SELECT * 쿼리를 실행하면 불필요한 데이터를 전송하게 되어 응답 속도가 느려질 수 있습니다.

3. 성능 최적화 및 설계 팁

테이블의 컬럼 수를 적정 수준으로 유지하면서 성능을 극대화하는 몇 가지 팁을 소개합니다.

  • 정규화: 데이터 중복을 줄이고 필수적인 정보만 남겨두는 정규화를 통해 불필요한 컬럼을 줄일 수 있습니다. 이렇게 하면 테이블이 더 간결해지고 관리가 쉬워집니다.
  • 데이터 타입 최적화: 컬럼의 데이터 타입을 최소한의 크기로 지정하여 데이터 저장 공간을 효율적으로 관리하세요. 예를 들어, 정수형 데이터에는 INT 대신 SMALLINT와 같은 작은 크기의 데이터 타입을 사용할 수 있습니다.
  • 인덱스 관리: 컬럼이 많을수록 인덱스 관리가 복잡해집니다. 필수적인 컬럼에만 인덱스를 추가하고, 자주 사용하지 않는 컬럼에는 인덱스를 추가하지 않는 것이 좋습니다.
  • 컬럼 그룹화: 비슷한 역할을 하는 컬럼들을 하나의 테이블에 모두 포함시키는 대신, 1:1 관계의 별도 테이블로 분리하는 방법을 고려할 수 있습니다. 예를 들어, 고객 정보를 저장하는 테이블에서 연락처 관련 컬럼을 별도의 테이블로 분리하면 쿼리 성능과 관리 효율이 개선될 수 있습니다.
  • JSONB 사용: 만약 컬럼이 1,600개에 가까워야 한다면, JSONB 데이터 타입을 활용해 비정형 데이터를 JSON 형태로 저장하는 것도 하나의 방법입니다. 이렇게 하면 유연한 구조로 다양한 데이터를 담을 수 있습니다.

4. 주의할 사항

테이블을 너무 많이 분리하면 JOIN 연산이 많이 발생하여 쿼리 성능이 저하될 수 있습니다. 데이터베이스 설계 초기 단계에서부터 컬럼 수를 최적화하는 것이 필요하며, 미래 확장성도 고려하여 테이블 설계를 진행해야 합니다.

결론

PostgreSQL에서 적절한 컬럼 수는 약 50~100개 수준입니다. 가능하다면 200개 이상의 컬럼을 포함하는 것을 피하는 것이 성능과 관리 측면에서 좋습니다. 데이터베이스 설계는 현재뿐만 아니라 향후 데이터 확장성과 성능을 고려한 장기적인 관점에서 접근해야 합니다.

728x90
반응형
반응형

아래와 같이 해당 BOOLEAN 타입의 컬럼 값을 반전시켜 저장하려고 하는 쿼리가 있습니다.

update table 
set column = !column 
where seq = 1

 

실행을 하면 오류가 발생하는데요 이유는 PostgreSQL에서 ! 연산자는 지원되지 않기때문입니다.

대신 NOT 키워드를 사용해야 합니다.

해결 방법

컬럼의 값을 반전시키기 위해 아래와 같이 쿼리를 수정합니다.

UPDATE table
SET column = NOT column
WHERE seq = 1;

 

설명

  • NOT column은  컬럼의 값을 True에서 False로, 또는 False에서 True로 반전시킵니다.
  • 컬럼이 BOOLEAN 타입일 때만 NOT 연산을 사용할 수 있습니다.
728x90
반응형
반응형

혼공 머신러닝 예제 진행 중 발생한 문제로

혼공 머신러닝의 경우 코렙사용을 기준으로 예제가 작성되다 보니 종종 직접 설치해야 하는 라이브러리들이 생깁니다.

!wget https://bit.ly/fruits_300_data -O fruits_300.npy

위의 코드도 그런 문제인데 실행해보면 ModuleNotFoundError: No module named ‘wget’ 이란 오류 메세지가 나오게 됩니다.

모듈을 못찾으니 conda list 또는 pip list로 설치된 모듈들을 확인 실제 존재 하지 않는다면( 당연히 없을 확률이 훨씬 높습니다)

conda install wget
or
pip intsll wget

설치를 하고 모듈을 설치 했으니 당연히 import wget 해서 모듈 import를 진행했는데 ModuleNotFoundError: No module named ‘wget’ 오류가 다시 나오게 됩니다.

wget은 리눅스 커널 명령어여서 그런지 import필요없이 처음 실행하고자 하는 코드를 그대로 실행하면 문제없이 파일 다운로드가 진행 됩니다.

구글링을 통해 다른 분들의 사례를 보면 설치 import를 해야 한다고 하는데 저는 오히려 import없이 진행해야 오류가 없던데 이유를 찾지는 못했네요.

참고로 wget 앞에 느낌표(!)는 리눅스 셸 명령임을 코드셸에 알려주기 위해 사용합니다.

728x90
반응형
반응형
let { type } = req.params;

위의 코드는 구조 분해 할당 (Destructuring Assignment)을 사용한 것입니다. . 아래는 이에 대한 상세 설명입니다.

 

1. req.params:

  • 이 코드는 Express.js 애플리케이션에서 사용됩니다. 여기서 req는 **요청 객체(request object)**입니다.
  • req.params는 URL에서 **경로 매개변수(route parameters)**를 담고 있는 객체입니다. 이 매개변수들은 일반적으로 경로에서 : 기호로 정의됩니다. 예를 들어:
app.get('/user/:type', (req, res) => {
  // req.params.type은 ':type'의 값을 가집니다
});
  • 경로가 /user/:type일 경우, type은 경로 매개변수가 되며, req.params는 다음과 같은 객체가 됩니다
{ type: 'someValue' }

 

2. 구조 분해 할당 (Destructuring Assignment):

  • { type } 구문은 구조 분해 할당입니다. 이는 객체에서 속성을 추출하는 간편한 방법입니다.
  • 원래는 다음과 같이 작성될 수 있습니다:
let type = req.params.type;

이를 아래와 같이 간략하게 작성할 수 있습니다:

let { type } = req.params;
 
  • 이 코드는 req.params 객체에서 type 속성을 추출하여 새로운 변수 type에 할당합니다.

요약

let { type } = req.params;는 req.params 객체에서 type이라는 매개변수를 추출하여 type이라는 변수에 저장하는 코드입니다. 이는 주로 Express.js에서 URL 경로의 매개변수를 쉽게 접근하기 위해 사용됩니다.

728x90
반응형
반응형

docker-compose ps 실행시 발생할 수 있는 오류

Traceback (most recent call last):
  File "urllib3/connectionpool.py", line 670, in urlopen
  File "urllib3/connectionpool.py", line 392, in _make_request
  File "http/client.py", line 1255, in request
  File "http/client.py", line 1301, in _send_request
  File "http/client.py", line 1250, in endheaders
  File "http/client.py", line 1010, in _send_output
  File "http/client.py", line 950, in send
  File "docker/transport/unixconn.py", line 43, in connect
ConnectionRefusedError: [Errno 61] Connection refused

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "requests/adapters.py", line 439, in send
  File "urllib3/connectionpool.py", line 726, in urlopen
  File "urllib3/util/retry.py", line 410, in increment
  File "urllib3/packages/six.py", line 734, in reraise
  File "urllib3/connectionpool.py", line 670, in urlopen
  File "urllib3/connectionpool.py", line 392, in _make_request
  File "http/client.py", line 1255, in request
  File "http/client.py", line 1301, in _send_request
  File "http/client.py", line 1250, in endheaders
  File "http/client.py", line 1010, in _send_output
  File "http/client.py", line 950, in send
  File "docker/transport/unixconn.py", line 43, in connect
urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionRefusedError(61, 'Connection refused'))

 

 

연결 거부라는 메시지가 포함이 되어 있어 혹시나 싶어 docker ps 명령을 실행하니 

Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

 

위와 같은 메시지가 출력이 되었네요.

 

이전에 docker desktop을 종료시켜 두었는데 다시 실행시키고 docker ps, docker-compose ps 명령을 실행하니 이상없이 실행이 됐습니다.

 

관련 오류를 검색해보면 환경변수같은 다른 이유도 있는 듯 한데 일단 docker가 실행되고 있는지 확인 필수 인거 같습니다.

728x90
반응형
반응형

Step1: 프로젝트 초기 설정

패키지 관리자는 yarn을 사용였습니다. 

먼저 프로젝트에 대한 새 디렉토리를 만들고 해당 디렉토리로 이동 후  Yarn 프로젝트를 초기화합니다.

mkdir my-project
cd my-project
yarn init -y

 

Step2: 프로젝트 초기 설정

Node.js, TypeScript, Express, TypeORM 및 PostgreSQL에 대한 패키지를 설치합니다.

yarn add express typeorm reflect-metadata pg
yarn add -D typescript ts-node @types/node @types/express

 

1. 'yarn add express typeorm reflect-metadata pg'

이 명령어는 express, typeorm, reflect-metadata, pg 패키지를 설치합니다. 이 패키지들은 프로젝트의 런타임 의존성으로 설치됩니다.

  • express: Node.js를 위한 빠르고 간단한 웹 프레임워크입니다. HTTP 서버를 쉽게 구축할 수 있게 해줍니다.
  • typeorm: TypeScript와 JavaScript(ES7, ES6, ES5)를 위한 ORM(Object Relational Mapper)입니다. 데이터베이스와 상호작용을 쉽게 해줍니다.
  • reflect-metadata: 메타데이터를 사용하여 객체지향 프로그래밍을 지원하는 데 필요한 라이브러리입니다. TypeORM에서 데코레이터 기능을 사용할 때 필요합니다.
  • pg: PostgreSQL 데이터베이스와 상호작용하기 위한 PostgreSQL 클라이언트입니다.

2. 'yarn add -D typescript ts-node @types/node @types/express'

이 명령어는 typescript, ts-node, @types/node, @types/express 패키지를 개발 의존성으로 설치합니다. 즉, 이 패키지들은 개발 중에만 필요하며, 프로덕션 빌드에는 포함되지 않습니다.

  • typescript: TypeScript 컴파일러입니다. TypeScript 코드를 JavaScript로 변환해줍니다.
  • ts-node: TypeScript 실행 환경입니다. TypeScript 코드를 실행할 수 있게 해줍니다.
  • @types/node: Node.js의 타입 정의 파일입니다. TypeScript에서 Node.js 내장 모듈을 사용할 때 타입 정보를 제공합니다.
  • @types/express: Express의 타입 정의 파일입니다. TypeScript에서 Express를 사용할 때 타입 정보를 제공합니다.

Step3: TypeScript 설정

프로젝트 루트경로에 tsconfig.json 파일을 생성하고 TypeScript 설정을 구성합니다.

{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "./dist",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}

 

Step4: TypeORM 구성 설정

프로젝트 루트경로에 src/data-source.ts 파일을 생성하고 설정을 구성합니다.

import "reflect-metadata";
import { DataSource } from "typeorm";
import { User } from "./entity/User";

export const AppDataSource = new DataSource({
  type: "postgres",
  host: "localhost",
  port: 5432,
  username: "your-username",
  password: "your-password",
  database: "your-database",
  synchronize: true,
  logging: false,
  entities: [User],
  migrations: [],
  subscribers: [],
});

 

'your-username', 'your-password', 'your-database'는 PostgreSQL 설치할때 설정 값으로 바꿉니다

 

Step:5 엔티티 생성

User 및 GenderStatistics 엔티티를 생성합니다.

User 엔티티

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id!: number;

  @Column()
  firstName!: string;

  @Column()
  lastName!: string;

  @Column()
  age!: number;
}

 

GenderStatistics 엔티티

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";

@Entity()
export class GenderStatistics {
  @PrimaryGeneratedColumn()
  num!: number;

  @Column({ nullable: true })
  poll_id!: string;

  @Column({ nullable: true })
  trait!: string;

  @Column({ nullable: true })
  gender!: string;

  @Column({ nullable: true })
  gender_cnt!: number;

  @Column("float", { nullable: true })
  rate!: number;
}

 

rate 필드는 소수점 값으로 저장할 수 있도록 설정하였습니다.

 

Step6: 리포지토리 생성

위의서 만든 각 엔티티에 해당하는 리포지토리를 생성하여 데이터베이스 작업을 처리합니다.

 

userRepository.ts

import { AppDataSource } from "../data-source";
import { User } from "../entity/User";

const userRepository = AppDataSource.getRepository(User);

export const createUser = async (userData: Partial<User>): Promise<User> => {
  const user = userRepository.create(userData);
  return await userRepository.save(user);
};

export const getUserById = async (id: number): Promise<User | null> => {
  return await userRepository.findOneBy({ id });
};

 

genderStatisticsRepository.ts

import { AppDataSource } from "../data-source";
import { GenderStatistics } from "../entity/GenderStatistics";

const genderStatisticsRepository = AppDataSource.getRepository(GenderStatistics);

export const createGenderStatistics = async (data: Partial<GenderStatistics>): Promise<GenderStatistics> => {
  const genderStat = genderStatisticsRepository.create(data);
  return await genderStatisticsRepository.save(genderStat);
};

export const getGenderStatisticsByNum = async (num: number): Promise<GenderStatistics | null> => {
  return await genderStatisticsRepository.findOneBy({ num });
};

 

Step7: 컨트롤러 생성

컨트롤러를 생성하여 HTTP 요청을 처리합니다.

 

userController.ts

import { Request, Response } from "express";
import { createUser, getUserById } from "../repositories/userRepository";

export const createUserHandler = async (req: Request, res: Response) => {
  try {
    const user = await createUser(req.body);
    res.status(201).json(user);
  } catch (error) {
    if (error instanceof Error) {
      res.status(500).json({ message: error.message });
    } else {
      res.status(500).json({ message: "An unknown error occurred" });
    }
  }
};

export const getUserByIdHandler = async (req: Request, res: Response) => {
  try {
    const user = await getUserById(parseInt(req.params.id));
    if (user) {
      res.json(user);
    } else {
      res.status(404).json({ message: "User not found" });
    }
  } catch (error) {
    if (error instanceof Error) {
      res.status(500).json({ message: error.message });
    } else {
      res.status(500).json({ message: "An unknown error occurred" });
    }
  }
};

 

genderStatisticsController.ts

import { Request, Response } from "express";
import { createGenderStatistics, getGenderStatisticsByNum } from "../repositories/genderStatisticsRepository";

export const createGenderStatisticsHandler = async (req: Request, res: Response) => {
  try {
    const genderStat = await createGenderStatistics(req.body);
    res.status(201).json(genderStat);
  } catch (error) {
    if (error instanceof Error) {
      res.status(500).json({ message: error.message });
    } else {
      res.status(500).json({ message: "An unknown error occurred" });
    }
  }
};

export const getGenderStatisticsByNumHandler = async (req: Request, res: Response) => {
  try {
    const genderStat = await getGenderStatisticsByNum(parseInt(req.params.num));
    if (genderStat) {
      res.json(genderStat);
    } else {
      res.status(404).json({ message: "Gender statistics not found" });
    }
  } catch (error) {
    if (error instanceof Error) {
      res.status(500).json({ message: error.message });
    } else {
      res.status(500).json({ message: "An unknown error occurred" });
    }
  }
};

 

Step8: 라우트 설정

userRoutes.ts

import { Router } from "express";
import { createUserHandler, getUserByIdHandler } from "../controllers/userController";

const router = Router();

router.post("/users", createUserHandler);
router.get("/users/:id", getUserByIdHandler);

export default router;

 

genderStatisticsRoutes.ts

import { Router } from "express";
import { createGenderStatisticsHandler, getGenderStatisticsByNumHandler } from "../controllers/genderStatisticsController";

const router = Router();

router.post("/gender-statistics", createGenderStatisticsHandler);
router.get("/gender-statistics/:num", getGenderStatisticsByNumHandler);

export default router;

 

Step9: Express 서버 설정

index.ts

import "reflect-metadata";
import express from "express";
import { AppDataSource } from "./data-source";
import userRoutes from "./routes/userRoutes";
import genderStatisticsRoutes from "./routes/genderStatisticsRoutes";

AppDataSource.initialize().then(() => {
  const app = express();

  app.use(express.json());

  app.use(userRoutes);
  app.use(genderStatisticsRoutes);

  const port = process.env.PORT || 3000;
  app.listen(port, () => {
    console.log(`Server is running on port ${port}`);
  });
}).catch(error => console.log(error));

 

모두 작성 되었다면 yarn dev로 개발 서버를 실행합니다.

 

자바스크립트 계열은 자료를 찾다보면 작성자마다 구조와 형식이 달라 늘 어렵네요.

728x90
반응형
반응형

JavaScript의 옵셔널 체이닝(Optional Chaining) 연산자 ?.는 객체의 속성에 접근할 때, 해당 속성이 존재하지 않더라도 에러를 발생시키지 않고 undefined를 반환하는 유용한 문법입니다. 이는 깊게 중첩된 객체 구조에서 속성에 접근할 때 특히 유용하며, 코드의 가독성과 안전성을 크게 향상시켜줍니다.

왜 옵셔널 체이닝이 필요한가?

객체의 속성에 접근할 때, 종종 해당 속성이 존재하지 않을 가능성을 고려해야 합니다. 예를 들어, 서버로부터 받은 데이터가 항상 동일한 구조를 가지지 않거나, 어떤 필드가 조건에 따라 존재하지 않을 수 있습니다. 이러한 상황에서 안전하게 속성에 접근하기 위해서는 많은 방어적 코드를 작성해야 합니다.

let person = {}; // person 객체는 비어있습니다.

console.log(person.contactInfo.address); // TypeError: Cannot read property 'address' of undefined

 

위의 코드에서 user.address가 undefined이기 때문에 user.address.street에 접근하려고 하면 오류가 발생합니다. 이 문제를 해결하기 위해 보통 아래와 같은 방어적 코드를 작성합니다.

let person = {};

if (person && person.contactInfo && person.contactInfo.address) {
  console.log(person.contactInfo.address);
} else {
  console.log('주소가 없습니다.');
}

 

하지만 이러한 방어적 코드는 가독성을 떨어뜨리고 작성하기 번거로울 수 있습니다. 이를 해결하기 위해 등장한 것이 옵셔널 체이닝 연산자입니다.

옵셔널 체이닝의 사용법

옵셔널 체이닝 연산자를 사용하면 중첩된 객체의 속성에 안전하게 접근할 수 있습니다. 옵셔널 체이닝은 ?. 형태로 사용되며, 해당 속성이 존재하지 않을 경우 undefined를 반환합니다.

let person = {}; // person 객체는 여전히 비어있습니다.

console.log(person?.contactInfo?.address); // undefined

 

위의 코드에서 user.address가 undefined이더라도 오류가 발생하지 않고 undefined를 반환합니다.

옵셔널 체이닝의 다양한 사용 예

1. 객체 속성 접근

let person = {
  fullName: 'John Doe',
  contactInfo: {
    address: '456 Elm St'
  }
};

console.log(person?.contactInfo?.address); // '456 Elm St'
console.log(person?.employment?.position); // undefined

 

2. 함수 호출

옵셔널 체이닝은 함수 호출에도 사용할 수 있습니다. 함수가 존재하지 않을 경우 undefined를 반환합니다.

let person = {
  sayHello: function() {
    console.log('Hi there!');
  }
};

person.sayHello?.(); // 'Hi there!'
person.sayGoodbye?.(); // 아무 일도 일어나지 않음

 

3. 배열 요소 접근

옵셔널 체이닝은 배열의 요소 접근에도 사용할 수 있습니다.

let employees = [{ fullName: 'John Doe' }, { fullName: 'Jane Smith' }];

console.log(employees[0]?.fullName); // 'John Doe'
console.log(employees[3]?.fullName); // undefined

 

결론

옵셔널 체이닝 연산자는 객체의 속성에 안전하게 접근할 수 있게 해주는 강력한 도구입니다. 이를 통해 코드의 가독성을 높이고, 중첩된 객체 구조를 다룰 때 발생할 수 있는 오류를 예방할 수 있습니다. JavaScript 코드에서 옵셔널 체이닝을 적절히 활용하면 보다 안정적이고 유지보수하기 쉬운 코드를 작성할 수 있습니다.

728x90
반응형
반응형

PostgreSQL에서 real, float, float8, double precision, numeric 타입은 모두 부동 소수점 숫자 또는 고정 소수점 숫자를 저장하는 데 사용됩니다. 각각의 차이점과 사용 방법, 그리고 활용 방안에 대해 알아보겠습니다.

데이터 타입 설명

  1. real
    • 설명: 4바이트 단정밀도 부동 소수점 숫자.
    • 정밀도: 약 6자리의 소수점 자릿수를 가짐.
    • 범위: -3.4E+38 ~ +3.4E+38.
    • 사용: 메모리가 제한적이고, 매우 높은 정밀도가 필요하지 않은 경우에 사용.
  2. float (또는 float8)
    • 설명: 8바이트 배정밀도 부동 소수점 숫자. float8은 double precision의 별칭입니다.
    • 정밀도: 약 15자리의 소수점 자릿수를 가짐.
    • 범위: -1.7E+308 ~ +1.7E+308.
    • 사용: 높은 정밀도가 필요한 경우에 사용.
  3. double precision
    • 설명: 8바이트 배정밀도 부동 소수점 숫자.
    • 정밀도: float와 동일, 약 15자리의 소수점 자릿수를 가짐.
    • 범위: float와 동일, -1.7E+308 ~ +1.7E+308.
    • 사용: 매우 높은 정밀도가 필요한 경우에 사용.
  4. numeric (또는 decimal)
    • 설명: 가변 길이의 정확한 숫자. 소수점 이하 자릿수와 전체 자릿수를 지정할 수 있음.
    • 정밀도: 사용자가 지정한 자릿수까지 정확함.
    • 범위: 매우 넓음, 제한이 없다고 볼 수 있음.
    • 사용: 금액 계산 등 매우 높은 정밀도가 요구되는 경우에 사용.

사용 방법과 예제

real

CREATE TABLE example_real ( id serial PRIMARY KEY, value real ); 
INSERT INTO example_real (value) VALUES (3.14), (2.71); 
SELECT * FROM example_real;

float (float8), double precision

CREATE TABLE example_float ( id serial PRIMARY KEY, value float8 ); 
CREATE TABLE example_double_precision ( id serial PRIMARY KEY, value double precision ); 
INSERT INTO example_float (value) VALUES (3.141592653589793), (2.718281828459045); 
INSERT INTO example_double_precision (value) VALUES (3.141592653589793), (2.718281828459045); 
SELECT * FROM example_float; SELECT * FROM example_double_precision;

numeric (decimal)

CREATE TABLE example_numeric ( id serial PRIMARY KEY, value numeric(10, 2) ); 
INSERT INTO example_numeric (value) VALUES (12345.67), (98765.43); 
SELECT * FROM example_numeric;
 

활용 방안

  1. real: 센서 데이터, 간단한 계산 등 정밀도가 크게 필요 없는 경우에 사용합니다.
  2. float (float8), double precision: 과학 계산, 통계 분석 등 높은 정밀도가 필요한 경우에 사용합니다. float8과 double precision은 동일한 타입이므로 동일한 용도로 사용됩니다.
  3. numeric (decimal): 금액, 금융 데이터 등 매우 높은 정밀도와 정확성이 필요한 경우에 사용합니다. 특히, 소수점 이하 자릿수가 중요한 경우 유용합니다.

요약

  • real은 4바이트 단정밀도 부동 소수점으로, 정밀도가 크게 필요 없는 경우에 사용됩니다.
  • float와 double precision은 8바이트 배정밀도 부동 소수점으로, 높은 정밀도가 필요한 경우에 사용됩니다.
  • numeric은 고정 소수점으로, 정밀도가 매우 중요한 경우에 사용됩니다.
728x90
반응형

+ Recent posts