[TIL - 1021] Spock가 뭐길래, 인덱스(1), int(11)이 뭘까?

test

spock 사용해보기

  • 기존에 자바 코드(+spring)를 테스트할 때는 JUnit(unit test), Mockito(integration test)을 사용해서 테스트를 했는데, 워크샵에서 groovy로 테스트 코드를 작성하는 것을 보고 무엇인지 보았더니 Spock 였음
/* build.gradle Spock 추가 : mvnrepo(Core Module) : 스프링 환경에서 테스트 하는 것이 아니므로 Core만 */
dependencies {
    testCompile group: 'org.spockframework', name: 'spock-core', version: '1.1-groovy-2.4'
}
  • junit과 비교했을 때 Spock는 어떤 특징을 가지는지 알아보았음
    • POJO 테스트
/* 테스트 대상 코드 */
public class Person {

    private static NameRule rule = BasicRule.of();
    private String name;

    public Person(String name) {
        if (!rule.isValid(name)) {
            throw new RuntimeException("올바르지않은 이름 설정");
        }
        this.name = name;
    }
}


/* Spock : 디펜던시 추가 후 테스트 클래스 생성할 때 테스트 프레임워크 선택할 수 있음 */
def "기본 룰 - 3자 미만"() {
    given:
    def invalidName = "te"
    
    when:
    new Person(invalidName)

    then
    def exception = thrown(RuntimeException.class)
    exception.message == "블라블라"
}

/* 여러가지 한꺼번에 테스트하기 */
def "기본룰 테스트"() {
    expect:
    new Person(name)

    where:
    name | _
    "jinbro" | _
    "te" | _
    "power" | _
    "qw" | _
}


#######
Condition failed with Exception:

new Person(invalidName)
|          |
|          te
java.lang.RuntimeException: 올바르지않은 이름 설정


Condition failed with Exception:

new Person(invalidName)
|          |
|          qw
java.lang.RuntimeException: 올바르지않은 이름 설정
  • 사용해보니
    • 조금 더 테스트하도록 유도하는 점(블록 없이는 실행안됨 - 로그만 찍어보기가 아니라 결과 관련 블록 있어야)이 있음
    • where 블록을 통해서 여러 케이스를 하나의 메소드로 묶어 테스트 할 수 있음 : 테스트 코드가 줄어듦 - JUnit의 경우 첫번쨰 실패 케이스만 알 수 있음
    • Mock 테스트도 가능함 : Mock() 함수를 통해서

MySQL

인덱스(1) - 레코드를 저장하는 방식

  • 검색 속도를 올리기 위한 레코드 저장 방식 : 검색(Select)속도를 올리는 대신 Insert, Update, Delete 속도는 느려짐
    • 인덱스를 재편집 해야하기 때문에 : B+Tree 구조로 정렬해둔 상태
    • 자주 사용되는 컬럼에 대해 인덱스를 걸어둠 : 검색 속도를 높여야할 필요성이 있는 데이터의 경우 불가피하게 선택할 수 밖에 없음

인덱스 종류

  • Clustered Index : PK를 인덱스(자동 생성), PK를 기준으로 실제 데이터 위치까지도 변경됨, PK를 기준으로 검색하여 빠른 속도로 검색
    • 인덱스의 Key가 PK
    • 레코드의 위치를 Value로 가지고 있음 : PK로 검색하면 빠르게 데이터 위치를 찾을 수 있음
    • BTree 구조
mysql> show index from employee\G;
*************************** 1. row ***************************
        Table: employee
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: id
    Collation: A
  Cardinality: 2
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
1 row in set (0.00 sec)

ERROR:
No query specified
  • Secondary Index(Non Clustered Index) : 해당 인덱스를 만들 때에는 데이터 정렬 자체도 변경되지않고(실제 데이터 위치 변경없음), 해당 컬럼 기준 B+Tree만 하나 더 만드는 것
    • PK를 Value로 가지고 있음 : PK를 찾아 Clustered Index로 다시 가서 레코드 위치를 찾음
    • BTree 구조
    • 풀스캔해서 찾는 것보다 트리구조로 되어있는 상태에서 검색하는 것이 더 빠름
    • FK는 자동으로 인덱스 생성
mysql > create index idx_employee_createdtime on employee (created_time);
  • Cardinality(인덱스 선정 기준 중 하나) : 사전의 뜻으로는 농도, 카디널리티가 높다는 뜻은 걸러낼 수 있는 데이터가 많다는 것
    • sex(성별 컬럼)를 인덱스로 잡을 경우 남/여 50%만 걸러낼 수 있으므로 성능상 이점을 가져갈 수 없음
    • 반대로 단순하게 auto_increment 설정된 int 타입의 Primary Key에 대한 인덱스가 자동생성되었는데, 각각 다 다르고 걸러내기가 쉬움(카디널리티가 높음)
  • index는 내일 데이터 bulk insert 해두고 테스트를 해봐야겠음

궁금했던 것 - int(11)에서 (11)은 무엇을 의미할까?

  • 디스플레이 옵션인데, 디스플레이할 때 비는 자리만큼 0을 채우도록(zerofill) 하는 옵션
    • 디스플레이 적용하기위해서는 컬럼 지정 시 zerofill로 선언해야함
    • int(11)을 사용하는 이유는? int가 4byte인데 unsigned 표현할 수 있는 데이터 범위가 21억… 10자리가 max size + 1
mysql > create table user ( id int(11) unsigned zerofill not null auto_increment, name varchar(16) not null, primary key (id) );
.
.
.
select * from user;
+-------------+------+
| id          | name |
+-------------+------+
| 00000000001 | a    |
| 00000000002 | b    |
| 00000000003 | c    |
| 00000000004 | d    |
| 00000000005 | e    |
+-------------+------+