MySQL 에서 흔히 볼 수 있 는 잘못된 디자인 규범 을 다 알 고 있 습 니까?

인터넷 의 발달 을 바탕 으로 우 리 는 언제 어디서나 차 를 기다 리 거나 지하철 을 타 는 파편 시간 을 이용 하여 정 보 를 배우 고 이해 할 수 있다.또한 발달 한 인터넷 은 사람들 이 자신의 지식 을 신속하게 공유 하고 같은 취미 와 수 요 를 가 진 친구 들 과 함께 토론 할 수 있 도록 도와 준다.
그러나 너무 편리 한 공유 도 지식 을 다양 하 게 만들어 잘못된 정 보 를 받 아들 이기 쉽다.이런 오류 가 가장 많은 것 은 기술 의 발전 이 빠 르 고 발표 한 내용 을 제때에 업데이트 할 여유 가 없 기 때문이다.뒤에서 공부 하 는 사람들 에 게 오 해 를 사지 않도록 오늘 MySQL 디자인 규범 에서 흔히 볼 수 있 는 몇 가지 잘못된 예 를 살 펴 보 겠 습 니 다.
메 인 키 의 디자인
잘못된 디자인 규범:홈 키 는 자체 ID 값 을 사용 하 는 것 을 권장 합 니 다.UUID,MD5,HASH,문자열 을 홈 키 로 사용 하지 마 십시오.
이 디자인 규범 은 많은 글 에서 볼 수 있 듯 이 홈 키 를 추가 하 는 장점 은 공간 이 작고 질서 가 있 으 며 사용 하기에 간단 하 다 는 등 장점 이 있다.
다음은 홈 키 의 단점 을 살 펴 보 자.
  • 자체 부가 가치 가 서버 에서 발생 하기 때문에 자체 적 으로 증가 하 는 AI 잠 금 보호 가 필요 하 다.이때 대량의 삽입 요청 이 있 으 면 자체 증가 로 인 한 성능 병목 이 존재 할 수 있 기 때문에 병행 성능 문제 가 존재 한다.
  • 자체 부가 가 치 를 메 인 키 로 하고 현재 사례 에서 만 유일 하 게 보장 할 수 있 으 며 전체 국면 에서 유일 하 게 보장 할 수 없 기 때문에 분포 식 구조 에서 사용 할 수 없다.
  • 데이터 값 을 공개 하면 안전 문 제 를 일 으 키 기 쉽 습 니 다.만약 에 저희 상품 ID 가 자체 증가 키 라면 사용 자 는 ID 값 을 수정 하여 상품 을 얻 을 수 있 습 니 다.심각 한 경우 에 저희 데이터 베이스 에 모두 얼마나 많은 상품 이 저장 되 어 있 는 지 알 수 있 습 니 다.
  • MGR(MySQL Group Replication)이 일 으 킬 수 있 는 성능 문제;
  • 자체 부가 가 치 는 MySQL 서버 에서 발생 하 는 값 이기 때문에 자체 적 으로 증가 하 는 AI 잠 금 보호 가 필요 하 다.이때 대량의 삽입 요청 이 있 으 면 자체 증가 로 인 한 성능 병목 이 존재 할 수 있다.예 를 들 어 MySQL 데이터베이스 에서 인자 innodbautoinc_lock_mode 는 자동 잠 금 보유 시간 을 제어 하 는 데 사 용 됩 니 다.비록,우 리 는 인자 innodb 를 조정 할 수 있 지만autoinc_lock_mode 는 자체 적 으로 증가 하 는 최대 성능 을 얻 었 으 나 다른 문제 가 있 기 때 문 입 니 다.따라서 동시 다발 장면 에 서 는 UUID 가 메 인 키 나 업무 사용자 정의 로 메 인 키 를 만 드 는 것 을 추천 합 니 다.
    우 리 는 MySQ L 에서 UUID()함 수 를 사용 하여 UUID 의 값 을 직접 얻 을 수 있 습 니 다.
    
    MySQL> select UUID();
    +--------------------------------------+
    | UUID()                               |
    +--------------------------------------+
    | 23ebaa88-ce89-11eb-b431-0242ac110002 |
    +--------------------------------------+
    1 row in set (0.00 sec)
    특히 주의해 야 할 것 은 저장 시간 에 UUID 는 시간 위치 에 따라 역순 으로 저장 된다 는 점 이다.즉,낮은 시간 에 낮은 위치 로 맨 앞 에 저장 되 고 높 은 시간 대 는 마지막 에 저장 된다 는 점 이다.즉,UUID 의 앞의 4 개의 바이트 는 시간의 변화 에 따라 끊임없이'랜 덤'으로 변화 하 며 단조 로 운 증가 가 아니다.임 의 값 이 아 닌 삽입 시 분 산 된 IO 가 발생 하여 성능 병목 이 생 긴 다.UUID 대비 부가 가치 가 가장 큰 폐단 이기 도 하 다.
    이 문 제 를 해결 하기 위해 MySQL 8.0 에서 함수 UUID 를 출시 하 였 습 니 다.TO_BIN,UUID 문자열 을:
  • 매개 변 수 를 통 해 시간 고 위 를 맨 앞 에 두 고 UUID 삽입 시 난 서 문 제 를 해결 했다.
  • 쓸모없는 문자열'-'를 제거 하고 저장 공간 을 간소화 합 니 다.
  • 문자열 을 바 이 너 리 값 으로 저장 하고 공간 은 최종 적 으로 36 개의 바이트 에서 16 바이트 로 단축 합 니 다.
  • 다음은 이전 UUID 문자열 23ebaa88-ce89-11eb-b431-0242ac 110002 를 함수 UUID 를 통 해TO_BIN 을 변환 하여 바 이 너 리 값 을 얻 으 면 다음 과 같 습 니 다.
    
    MySQL> SELECT UUID_TO_BIN('23ebaa88-ce89-11eb-b431-0242ac110002',TRUE) as UUID_BIN;
    +------------------------------------+
    | UUID_BIN                           |
    +------------------------------------+
    | 0x11EBCE8923EBAA88B4310242AC110002 |
    +------------------------------------+
    1 row in set (0.01 sec)
    이외에 도 MySQL 8.0 은 함수 BIN 을 제공 합 니 다.TO_UUID,바 이 너 리 값 을 UUID 문자열 로 반전 하 는 것 을 지원 합 니 다.
    MySQL 8.0 버 전에는 함수 가 없 었 지만 UUIDTO_BIN/BIN_TO_UUID,사용자 정의 함수 로 해결 할 수 있 습 니 다.응용 층 은 자신의 프로 그래 밍 언어 에 따라 해당 하 는 함 수 를 작성 할 수 있 습 니 다.
    물론 많은 학생 들 이 UUID 의 성능 과 저장 공간 문 제 를 걱정 합 니 다.여기 서 저도 관련 삽입 성능 테스트 를 했 는데 결 과 는 다음 과 같 습 니 다.

    MySQL 8.0 이 제공 하 는 정렬 UUID 는 자체 ID 증가 보다 성능 이 가장 좋 은 것 으로 나 타 났 다.또한 UUIDTO_BIN 이 전환 한 결과 16 바이트 로 자 증 ID 보다 8 바이트 늘 어 나 는 데 그 쳤 고,마지막 에 저장 소 가 차지 하 는 공간 도 자체 보다 3G 늘 어 나 는 데 그 쳤 다.
    또한 UUID 는 전체 국면 에서 유일 하 게 사용 할 수 있 기 때문에 UUID 를 사용 하 는 수익 은 자체 증가 ID 보다 훨씬 크다.셀 프 키 를 메 인 키 로 사용 하 는 것 에 익숙 해 졌 는 지 모 르 겠 지만,동시 다발 장면 에 서 는 UUID 와 같은 전역 유일 치 를 메 인 키 로 사용 하 는 것 을 추천 합 니 다.
    물론 UUID 는 좋 지만 분포 식 장면 에서 메 인 키 는 추가 정 보 를 추가 해 야 후속 2 급 색인 조회 효율 을 확보 할 수 있 습 니 다.업무 사용자 정의 에 따라 메 인 키 를 만 드 는 것 을 추천 합 니 다.하지만 병발 량 과 데이터 양 이 그리 많 지 않 은 경우 에는 자체 증가 UUID 를 추천 합 니 다.여러분 은 UUID 가 메 인 키 가 될 수 없다 고 생각 하지 마 세 요.
    금융 필드 의 설계
    잘못된 디자인 규범:재무 와 관련 된 금액 류 데 이 터 는 decimal 형식 을 사용 해 야 합 니 다.float 와 double 은 모두 정확 하지 않 은 부동 소수점 유형 이 고 decimal 은 정확 한 부동 소수점 유형 입 니 다.그래서 일반적으로 사용자 잔액,상품 가격 등 금융 필드 를 디자인 할 때 보통 decimal 유형 을 사용 하여 정확하게 구분 할 수 있다.
    그러나 수많은 인터넷 업무 의 디자인 기준 에서 DECIMAL 유형 을 추천 하지 않 고 DECIMAL 을 정형 유형 으로 전환 하 는 것 을 추천 합 니 다.즉,금융 유형 은 원 단위 가 아 닌 분 단위 로 저장 하 는 것 을 추천 하 는 것 이다.예 를 들 어 1 원 이 데이터베이스 에 정형 유형 100 으로 저장 된다.
    다음은 bigint 유형의 장점:
  • decimal 은 바 이 너 리 를 통 해 이 루어 진 인 코딩 방식 으로 계산 효율 이 bigint
  • 보다 못 하 다.
  • bigint 를 사용 하면 필드 는 고정 필드 로 저장 이 효율 적 이 고 decimal 은 정 의 된 너비 에 따라 데이터 디자인 에서 고정 저장 성능 이 더욱 좋다
  • .
  • bigint 를 사용 하여 단위 로 나 누 는 금액 을 저장 할 수도 있 고 천조 급 의 금액 을 저장 할 수도 있어 충분히 사용 할 수 있다
  • 매 거 필드 사용
    잘못된 디자인 규범:ENUM 형식 사용 피하 기
    이전 개발 프로젝트 에서 사용자 성별,상품 이 올 라 가 는 지,숨 기 는 지 등 필드 를 만 났 을 때 필드 를 tinyint 로 간단하게 설계 한 다음 필드 에 0 왜 상태,1 왜 상 태 를 설명 합 니 다.
    이런 디자인 의 문제 도 비교적 뚜렷 하 다.
  • 잘 표현 되 지 않 습 니 다.이 표 는 다른 동료 가 디자인 한 것 일 수도 있 습 니 다.인상 이 깊 지 않 으 면 매번 필드 주석 을 봐 야 합 니 다.심지어 인 코딩 할 때 데이터 베 이 스 를 통 해 필드 의 의 미 를 확인 해 야 합 니 다
  • .
  • 더러 운 데이터:응용 층 에서 코드 를 통 해 삽 입 된 수 치 를 제한 할 수 있 지만 sql 과 시각 화 도 구 를 통 해 값 을 수정 할 수 있 습 니 다
  • 이 고정 옵션 값 의 필드 는 ENUM 매 거 진 문자열 형식 과 SQL 을 사용 하 는 것 을 추천 합 니 다.MODE 의 엄격 한 패턴
    MySQL 8.0.16 이후 버 전에 서 check 제약 체 제 를 직접 사용 할 수 있 습 니 다.enum 매 거 진 필드 형식 을 사용 하지 않 아 도 됩 니 다.
    그리고 우 리 는 일반적으로 매 거 진 값 을 정의 할 때'Y','N'등 단일 문 자 를 사용 하 며 많은 공간 을 차지 하지 않 습 니 다.그러나 옵션 값 이 고정 되 지 않 으 면 업무 발전 에 따라 증가 할 수 있 으 므 로 매 거 진 필드 를 추천 하지 않 습 니 다.
    인덱스 개수 제한
    잘못된 디자인 규범:표 마다 색인 수량 을 제한 하고 표 한 장의 색인 은 5 개 를 초과 할 수 없습니다.
    MySQL 시트 의 색인 은 개수 제한 이 없습니다.업무 조회 에 구체 적 인 필요 가 있 습 니 다.만 들 면 됩 니 다.개수 제한 을 미신 하지 마 십시오.
    하위 조회 사용
    잘못된 디자인 규범:하위 검색 사용 피하 기
    사실 이 규범 은 기 존 버 전의 MySQL 에 있어 서 옳 습 니 다.기 존 버 전의 MySQL 데이터 베 이 스 는 하위 조회 최적화 에 한계 가 있 기 때문에 많은 OLTP 업무 상황 에서 우 리 는 온라인 업무 가 가능 한 한 하위 조 회 를 사용 하지 않도록 요구 합 니 다.
    그러나 MySQL 8.0 버 전에 서 는 하위 검색 의 최적화 가 크게 향상 되 었 기 때문에 새 버 전의 MySQL 에 서 는 하위 검색 을 안심 하고 사용 할 수 있 습 니 다.
    하위 조 회 는 JOIN 보다 인류 가 이해 하기 쉽다.예 를 들 어 우 리 는 2020 년 에 글 을 보 내지 않 은 친구 의 수 를 보고 싶다.
    
    SELECT COUNT(*)
    FROM user
    WHERE id not in (
        SELECT user_id
        from blog
        where publish_time >= "2020-01-01" AND  publish_time <= "2020-12-31"
    )
    하위 검색 의 논 리 를 볼 수 있 습 니 다.not IN 을 통 해 글 표를 조회 하 는 사용자 가 어떤 것 이 있 는 지 알 수 있 습 니 다.
    하면,만약,만약...
    
    SELECT count(*)
    FROM user LEFT JOIN blog
    ON user.id = blog.user_id and blog.publish_time >= "2020-01-01" and blog.publish_time <= "2020-12-31"
    where blog.user_id is NULL;
    LEFT JOIN 도 이 같은 수 요 를 달성 할 수 있 지만 이해 하기 쉽 지 않 은 것 으로 나 타 났 다.
    우 리 는 explain 을 사용 하여 두 sql 의 실행 계획 을 보 았 는데,모두 같은 것 을 발견 하 였 다.

    위의 그림 을 통 해 알 수 있 듯 이 하위 조회 든 LEFT JOIN 이 든 모두 left hash Join 으로 전환 되 었 기 때문에 상기 두 SQL 의 실행 시간 은 같다.즉,MySQL 8.0 에 서 는 유 틸 리 티 가 자동 으로 IN 서브 쿼 리 를 최적화 해 최 적의 JOIN 실행 계획 으로 최적화 해 성능 을 현저하게 향상 시킨다.
    총결산
    앞의 내용 을 읽 고 여러분 들 이 MySQL 에 대해 새로운 인식 을 가지 게 되 었 다 고 믿 습 니 다.이런 흔히 볼 수 있 는 오 류 는 다음 과 같은 몇 가지 로 요약 할 수 있 습 니 다.
  • UUID 도 메 인 키 로 사용 할 수 있 습 니 다.자체 증가 UUID 는 자체 증가 메 인 키 보다 성능 이 좋 고 많이 사용 하 는 공간 도 무시 할 수 있 습 니 다
  • 금융 필드 는 decimal 을 제외 하고 bigint 를 시도 하여 단위 로 나 뉘 는 데 이 터 를 저장 할 수 있다
  • .
  • 고정 옵션 값 의 필드 에 대해 MySQL 8 은 이전에 매 거 진 필드 를 추천 하 였 으 며,MySQL 8 이후 check 함수 제약 을 사용 하 였 으 며,0,1,2 표시
  • 를 사용 하지 않 았 습 니 다.
  • 한 장의 표 의 색인 개 수 는 제한 이 없고 5 개 를 초과 할 수 없 으 며 업무 상황 에 따라 추가 하고 삭제 할 수 있다
  • .
  • MySQL 8 쌍 의 하위 조회 가 최적화 되 어 안심 하고 사용 할 수 있 습 니 다.
  • MySQL 에서 흔히 볼 수 있 는 오류 디자인 규범 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 MySQL 오류 디자인 규범 에 관 한 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 저 희 를 많이 사랑 해 주세요!

    좋은 웹페이지 즐겨찾기