반응형

오라클 아이디, 비밀번호 필요하니까 가입하자!

 

 

https://www.oracle.com/

 

Oracle | Integrated Cloud Applications and Platform Services

Autonomous Database for Dummies Find out how your Oracle Database can install, manage, secure, and upgrade itself. That’s all possible today, thanks to the power of machine learning, artificial intelligence (AI), and the cloud.

www.oracle.com

https://www.oracle.com/kr/database/technologies/appdev/sql-developer.html

 

SQL Developer | Oracle 대한민국

Oracle SQL Developer Oracle SQL Developer is a free, integrated development environment that simplifies the development and management of Oracle Database in both traditional and Cloud deployments. SQL Developer offers complete end-to-end development of you

www.oracle.com

https://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index.html

 

Oracle SQL Developer Downloads

 

www.oracle.com

 

반응형
반응형
SQL for Beginners in a Nutshell

반응형
반응형

Realm은 어떻게 효율적인
 데이터베이스를 만들었나?

https://deview.kr/2017/schedule/206


Realm은 SQLite만 사용되던 모바일 데이터베이스 시장에서 혁신적인 대안으로 평가받고있는 오픈소스 데이터베이스 입니다. 현재 10만명 이상의 개발자들이 개발에 사용하고있고, 20억대 이상의 디바이스에 설치되어 있습니다. 


Realm을 빠르고 효율적인 데이터베이스로 만들기 위해 사용되었던 여러 기술과 고려되었던 여러 사안들이 있습니다. Realm이 이슈들을 어떤 방법으로 대처해왔는지를 살피고 거기에서 응용과 프레임워크 개발에서 얻을 수 있는 교훈을 살펴봅시다.




how can realm_make_efficient_mobile_database

1. Realm은 어떻게 효율적인 데이터베이스를 만들었나? Leonardo YongUk Kim Java team

2. GreenDao ORMLite SQLite Realm

3. 첫번째 비결 Zero copy

4. Zero copy “최대한 복제를 미루는 것입니 다.”

5. 왜 Zero copy인가? 

public class City { private String name; private long votes; 

public String getName() { return name; } 

public void setName(String name) { this.name = name; } 

public long getVotes() { return votes; } 

public void setVotes(long votes) { this.votes = votes; } } 

제로 카피 없는 세상을 생각해 봅시다.

6. 왜 Zero copy인가? 

public class City { 

private String name; private long votes; 

public String getName() { return name; } 

public void setName(String name) { this.name = name; } 

public long getVotes() { return votes; } 

public void setVotes(long votes) { this.votes = votes; }

 }

ORM이나 JSON 파서가 채워줘야 해요. 

ORM이나 JSON 파서가 채워줘야 해요.

7. 왜 Zero copy인가? public class City { private String name; private long votes; public String getName() { return name; } public void setName(String name) { this.name = name; } public long getVotes() { return votes; } public void setVotes(long votes) { this.votes = votes; } } public List<City> hydrate() { List<City> results = new ArrayList<>(); while (hasNextItem) { City c = new City(); c.setName(name); c.setVotes(votes); results.add(c); } return results; } 너가 뭘 쓸지 몰라서 다 준비했어요.

8. 왜 Zero copy인가? public List<City> hydrate() { List<City> results = new ArrayList<>(); while (hasNextItem) { City c = new City(); c.setName(name); c.setVotes(votes); /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ results.add(c); } return results; } 너가 뭘 쓸지 몰라서 다 준비했어요. 수화라고 번역합니다. 객체의 필드를 채우는 일입니다.

9. 왜 Zero copy인가? public List<City> hydrate() { List<City> results = new ArrayList<>(); while (hasNextItem) { City c = new City(); c.setName(String.valueOf(name)); c.setVotes(Integer.parseInt(votes)); /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ /* invoke other setters */ results.add(c); } return results; } 어쩌면 매번 변환이 필요할지 몰라Yo~!

10. 왜 Zero copy인가? public class City { private String name; private long votes; public String getName() { return name; } public void setName(String name) { this.name = name; } public long getVotes() { return votes; } public void setVotes(long votes) { this.votes = votes; } } 만약에 사용자가 getName만 필요하면? votes값의 변환과 설정은 필요없는 것 아닌가?

11. 왜 Zero copy인가? public class City { private String name; private long votes; private final int COLUMN_NAME = 0; public String getName() { return (String) getRow().getSting(COLUMN_NAME); } public void setName(String name) { getRow().setString(COLUMN_NAME, name); } public long getVotes() { return votes; } public void setVotes(long votes) { this.votes = votes; } } row에서 해당 column만 이제 가져옵시다. name을 채우지 맙시다. row의 해당 column에 기록합니다. “사용하지 않을지 모르는 항목을 위한 작업을 최대한 뒤로 미루자.”

12. 보일러플레이트

13. 보일러플레이트 public class City { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } public class City { private final int COLUMN_NAME = 0; public String getName() { return (String) getRow().getSting(COLUMN_NAME); } public void setName(String name) { getRow().setString(COLUMN_NAME, name); } } 프로그래머에게 직관적인 코드

14. 보일러플레이트 public class City { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } public class LazyCity { private final int COLUMN_NAME = 0; public String getName() { return (String) getRow().getSting(COLUMN_NAME); } public void setName(String name) { getRow().setString(COLUMN_NAME, name); } } 프로그래머에게 비관적인 코드 꼭 이렇게 짜야하나요?

15. 보일러플레이트 public class City extends RealmObject { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } public class CityRealmProxy extends City{ private final int COLUMN_NAME = 0; public String getName() { return (String) getRow().getSting(COLUMN_NAME); } public void setName(String name) { getRow().setString(COLUMN_NAME, name); } } 반복적인 작업은 기계에게 맡겨야 합니다. “Annotation Processing Tool (APT)” 생성된 클래스는 모두 RealmProxy가 붙습니다.Realm 객체는 RealmObject를 상속 받습니다.

16. 반복적인 작업은 기계에게 맡겨야 합니다.

 “Annotation Processing Tool (APT)” 

“어노테이션 프로세싱 툴은 어노테이션으로 부터 새로운 객체를 생성합니다.”


17. Man vs Code 

City CityRealmProx y 사용자의 원본 객체 (RealmObject) 기계가 생성한 객체 (RealmProxy) 어노테이션 프로세싱 툴 (APT)


18. Man vs Code Realm의 APT는 AbstractProcessor를 상속한 RealmProcessor로 구현됩니다. AbstractProcessor +process(annotations, roundEnv) RealmProcessor RealmObject RealmProxy RealmObject RealmProxy RealmObject RealmProxy

19. Man vs Code writer.emitAnnotation("Override") .beginMethod( "void", // return type "copy", // method name EnumSet.of(Modifier.PROTECTED, Modifier.FINAL), // modifiers "ColumnInfo", "rawSrc", "ColumnInfo", "rawDst"); // parameters writer.emitStatement("final %1$s src = (%1$s) rawSrc", columnInfoClassName()); writer.emitStatement("final %1$s dst = (%1$s) rawDst", columnInfoClassName()); for (VariableElement variableElement : metadata.getFields()) { writer.emitStatement("dst.%1$s = src.%1$s", columnIndexVarName(variableElement)); } writer.endMethod(); “마법은 없습니다. Java 코드를 생성하는 것은 고통스러운 일입니다.”

20. Man vs Code “마법은 없습니다. Java 코드를 생성하는 것은 고통스러운 일입니다.” 1. StringBuilder 2. Template engines 1. Apache Velocity (7년만에 부활) 2. Apache FreeMaker 3. Pebble Template Engine 4. Thymeleaf Template Engine 3. Code generators 1. JavaPoet 2. JavaWriter (개발 중단. Java Poet이 후속작) 3. jcodemodel (2005년 경부터 개발 중단) 당신은 용자 코드도 찍어내면 그만? 내가 코드를 짜는 건지 코드가 날 짜는 건지. 튜토리얼이 많은 애가 개발이 잘 안돼. 그래도 스퀘어가 제일 낫지 않나?

21. APT가 해법인가?

22. APT가 해법인가? public class City extends RealmObject { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } public class CityRealmProxy extends City { private final int COLUMN_NAME = 0; public String getName() { return (String) getRow().getSting(COLUMN_NAME); } public void setName(String name) { getRow().setString(COLUMN_NAME, name); } } APT는 어떤 메서드가 어떤 역할인지 이해하지 못합니다.

23. APT가 해법인가? public class City extends RealmObject { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } public class CityRealmProxy extends City { private final int COLUMN_NAME = 0; public String getName() { return (String) getRow().getSting(COLUMN_NAME); } public void setName(String name) { getRow().setString(COLUMN_NAME, name); } } 암묵적인 컨벤션을 가정합니다. 구 버전의 Realm에서는 항상 표준적인 이름의 getter와 setter를 강제합니다. name이란 필드에 대해 getName과 setName을 쓰지 않을까요?

24. APT가 해법인가? public class City extends RealmObject { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } public class CityRealmProxy extends City { private final int COLUMN_NAME = 0; public String getName() { return (String) getRow().getSting(COLUMN_NAME); } public void setName(String name) { getRow().setString(COLUMN_NAME, name); } } 부모가 name 필드와 어떤 상호작용을 하고 있을지 예상할 수 없습니다. 구 버전의 Realm은 커스텀 동작을 금지하고 부모 클래스의 동작을 무시했습니다. City의 getName은 어떤 부가 작업을 하고 있을까요? City의 setName은 어떤 부가 작업을 하고 있을까요?

25. 바이트 코드 뒤집기

26. 바이트 코드 뒤집기 City name CityRealmProx y CityRealmProxyInterface +realmGet$name: String +realmSet$name(name) ZeroCopy관련 객체를 위한 인터페이스 name 필드에 접근하는 모든 코드 대신 realmGet$name과 realmSet$name이 호출되도록 변조합 니다. realmGet$name과 realmSet$name를 오버라이드해서 Zero copy 부분을 구현합니다. APT로 코드 생성 인터페이스 구현

27. 바이트 코드 뒤집기 public class CityRealmProxy extends City implements CityRealmProxyInterface { private final int COLUMN_NAME = 0; public String realmGet$name() { return (String) getRow().getSting(COLUMN_NAME); } public void realmSet$Name(String name) { getRow().setString(COLUMN_NAME, name); } } 내부용 게터와 세터는 RealmProxy 아래 생성됩니다.

28. 바이트 코드 뒤집기 public class City implements CityRealmProxyInterface { private String name; public String getName() { return (String) realmGet$name(); } public void setName(String name) { realmSet$name(name); } public String realmGet$name() { return name; } public void realmSet$Name(String name) { this.name = name; } } “바이트코드가 변조된 City객체 입니다.” public class City extends RealmObject { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }

29. 바이트 코드 뒤집기 public class City implements CityRealmProxyInterface { public String name; public String realmGet$name() { return name; } public void realmSet$Name(String name) { this.name = name; } } “이제는 getter와 setter가 없어도 됩니다.” public class City extends RealmObject { public String name; } name 필드에 대한 접근은 모두 게터와 세터 호출로 변경됩니다.

30. 바이트 코드 뒤집기 City CIty 사용자가 생성한 객체 바이트 코드 변조된 객체 Transformer “Transformer는 빌드된 결과를 변조합니다.”

31. 바이트 코드 뒤집기 class RealmTransformer extends Transform { @Override void transform(Context context, Collection<TransformInput> inputs, Collection<TransformInput> referencedInputs, TransformOutputProvider outputProvider, boolean isIncremental) throws IOException, TransformException, InterruptedException { … } } 이 트랜스포머가 필드에 대한 접근들을 모두 Realm의 게터와 세터로 변조합니다.

32. 바이트 코드 뒤집기 “마법은 없습니다. 바이트 코드를 변조하는 것은 고통스러운 일입니다.” 1. ASM 2. BCEL 3. CGLIB 4. Javassist 5. AspectJ 중간 정도 난이도의 도구. Realm이 사용.

33. 다른 DB도 Zero copy?

34. 다른 DB도 Zero copy? SQLite 시스템 적인 경계 Object Object Object Object Object Object ORM

35. 다른 DB도 Zero copy? SQLite 시스템 적인 경계 Object Object Object Object Object Object ORM 이 영역까지만 lazy하게 미룰 수 있음.

36. 다른 DB도 Zero copy? SQLite 시스템 적인 경계 Object Object Object Object Object Object ORM 경계를 넘어서 lazy한 처리는 어려움.

37. 더 많은 Zero copy 가능성 realm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { Person person = realm.createObject(Person.class); person.setId(1); person.setName("Young Person"); person.setAge(14); } }); final RealmResults<Person> people = realm.where(Person.class).findAll(); final Person person = people.first(); final String name = person.name; “Realm은 생각보다 더 게으릅니다.”

38. 더 많은 Zero copy 가능성 realm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { Person person = realm.createObject(Person.class); person.setId(1); person.setName("Young Person"); person.setAge(14); } }); final RealmResults<Person> people = realm.where(Person.class).findAll(); final Person person = people.first(); final String name = person.name; Realm 은 오프셋도 리미트도 없습니다.

39. 더 많은 Zero copy 가능성 realm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { Person person = realm.createObject(Person.class); person.setId(1); person.setName("Young Person"); person.setAge(14); } }); final RealmResults<Person> people = realm.where(Person.class).findAll(); final Person person = people.first(); final String name = person.name; 이 시점에서는 실제 데이터를 받아오지 않습니다. 실제 데이터를 가지고 있지 않기 때문에 특수한 리스트 구조를 가지고 있습 니다.

40. 더 많은 Zero copy 가능성 realm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { Person person = realm.createObject(Person.class); person.setId(1); person.setName("Young Person"); person.setAge(14); } }); final RealmResults<Person> people = realm.where(Person.class).findAll(); final Person person = people.first(); final String name = person.name; 이 시점에 첫 번째 사람에 대한 메타 데이터만 가지고 옵니다.

41. 더 많은 Zero copy 가능성 realm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { Person person = realm.createObject(Person.class); person.setId(1); person.setName("Young Person"); person.setAge(14); } }); final RealmResults<Person> people = realm.where(Person.class).findAll(); final Person person = people.first(); final String name = person.name; 이 시점에 첫 번째 사람의 정보 중 name만 접근합니다.

42. 더 많은 Zero copy 가능성 Realm은 lazy하게 동작하기 위해 특별한 클래스를 가집니다. 1. RealmObject 2. RealmResults 3. RealmList DB 엔진의 지원 때문에 전체적으로 게을러질 수 있습니다.

43. 조금 더 빨라지기 위 해

44. 조금 더 빨라지기 위해 final RealmResults<Person> people = realm.where(Person.class).findAll(); for (Person person : people) { final String name = person.name; } 객체의 전체 필드가 필요한 경우는 드뭅니다. 모바일 데이터베이스의 특징을 생각해봅시다.

45. 조금 더 빨라지기 위해 10 30 40 3 4 6 10 Row 3 전통적인 Row 우선 B-Tree리프가 10번째 Row까지 가진다는 것을 의미 nam e votes 패딩 리프는 보통 연속된 Array Row에 속한 모든 Column

46. 조금 더 빨라지기 위해 10 30 40 3 4 6 10 Row 3 연속된 name 검색 nam e votes 패딩 인접한 데이터는 name이 아니다.

47. 조금 더 빨라지기 위해 캐시를 생각해봅시다. (3회 적중) nam e votes 패딩 nam e votes 패딩 nam e votes 패딩 nam e votes 패딩 캐시 라인 캐시 히트 캐시 미스

48. 조금 더 빨라지기 위해 구조를 컬럼 기준으로 바꾸어봅시다. nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e 캐시 라인

49. 조금 더 빨라지기 위해 구조를 컬럼 기준으로 바꾸어봅시다. (12회 적중) nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e nam e 캐시 라인 캐시 히트 캐시 미스

50. 조금 더 빨라지기 위해 4 8 12 Realm의 Column 우선 B-Tree nam e nam e nam e nam e 리프가 4번째 컬럼까지 가진다는 것을 의미 동질적인 데이터이기에 예측가능한 사이즈

51. 4 8 12 Realm의 전체 트리 nam e nam e nam e nam e nam e votes Perso n Group (DB와 같은 개념) Table Column B-tree 4 8 12 vote votes votes votes Ro ot

52. Root가 있는 이유?

53. Root가 있는 이유? 4 8 12 nam e nam e nam e nam e nam e votes Perso n 4 8 12 vote votes votes votes Ro ot 전체 Group을 하나의 스냅샷으로 인 지.

54. Root가 있는 이유? 현재 버전을 포인팅 Ro ot 현재 버전 삭제될 과거 버전 “Multi Version Concurrency Control” Git, 현대적인 DBMS에서 사용.

55. Root가 있는 이유? Ro ot 다른 사용자는 현재 버전에 Lock 없이 접근. 새 버전을 작성중 . 읽기는 언제나 비 배타적입니다.

56. Root가 있는 이유? Ro ot 새로 작성된 버전으로 옮겨가는 것만 락이 필요합 니다. Ro ot 쓰기만 배타적입니다. 다른 사용자는 여전히 이전 버전에 접근 중. 루트를 이동

57. Root가 있는 이유? "MVVC는 효율을 위해 사용성을 일부 희생합니다.” 1. 읽기는 Lock이 필요하지 않으며 언제나 가능합니다. 2. 쓰기는 Lock이 필요합니다. 3. 객체는 어떤 시점을 참고하고 있기 때문에 다른 스레드로 전달될 수 없습니 4. 다른 스레드에서 객체를 참고하는 것은 즉시 이루어집니다. 프로그래머에게 직관적이지는 않습니다.

58. 이전 버전을 읽을 가 능성?

59. 이전 버전을 읽을 가능성? Ro ot 다른 사용자는 현재 버전에 Lock 없이 접근. 새 버전을 작성중 . “다른 사용자는 여전히 구 버전을 접근하게 되지 않나요?”

60. 이전 버전을 읽을 가능성? Person 객체 (Leonardo) v1 Person 객체 (Leonardo) v1 스레드 A 스레드 B Person 객체 (Leonardo) v2 1. 스레드 A에서 Person 객체 업데이트. 2. 업데이트 내역이 전파. Person 객체 (Leonardo) v2 3. 스레드 B의 라이브 객체가 자동 업데이 트. 3. 스레드 B의 객체의 리스너에게 모두 업데이트 내용을 통보.

61. 추가적인 최적화

62. 추가적인 최적화 4 8 12 nam e nam e nam e nam e nam e votes Perso n 배열은 얼마나 많은 공간을 차지할까? 4 8 12 vote votes votes votes Ro ot

63. 추가적인 최적화 0 1 0 1 votes가 최대 1인 경우 “최대 값이 1인 경우 4개의 votes는 4bits를 차지합니다.” Boolean 타입이 가장 효율적으로 저장됩니다.

64. 추가적인 최적화 00 01 10 01 최대 값이 2로 변경되었습니다. “최대 값이 2인 경우 4개의 votes는 8bits를 차지합니다.”

65. 추가적인 최적화 000 101 010 001 최대 값이 5로 변경되었습니다. “최대 값이 5인 경우 4개의 votes는 12bits를 차지합니다.”

66. 추가적인 최적화 4 8 12 노드의 실제 구조 nam e nam e nam e nam e nam e votes Perso n 4 8 12 vote votes votes votes Ro ot 4 8 12 개별 노드는 3개의 배열을 사용합니 다. 유연하지만 오버헤드가 있습니다.

67. 추가적인 최적화 nam e votes Perso n vote votes votes votes 4 8 12 만약에 데이터가 뒤로만 추가된다면 더 최적화를 할 수 있습니 다. 모든 노드가 다 차있다면 처음과 마지막 인덱스만 있으면 됩 니다.

68. 추가적인 최적화 nam e votes Perso n vote votes votes votes 4 12 물론 이러한 꿈은 삽입과 삭제가 이뤄지면 물거품이 됩니다. 모든 노드가 다 차있다면 처음과 마지막 인덱스만 있으면 됩 니다.

69. 흥미로운가요?


70. 기회는 여러분에게 열려있습니다. “Realm은 오픈소스입니다.”

Realm Java https://github.com/realm/realm-java 

Realm Objective C & Swift https://github.com/realm/realm-cocoa 

Realm Xamarin https://github.com/realm/realm-dotnet 

Realm Reactive Native & Node.js https://github.com/realm/realm-js 

Realm Object Store 공통 모듈 https://github.com/realm/realm-object-store 

Realm Core 핵심 엔진 https://github.com/realm/realm-core


71. Realm을 바로 사용하실 수 있습니다. 

Realm Java 문서 https://realm.io/docs/java/latest/ 

Realm Swift 문서 https://realm.io/docs/swift/latest/ 

Realm Objective C 문서 https://realm.io/docs/objc/latest/ 

Realm React Native 문서 https://realm.io/docs/javascript/latest/ 

Realm Xamarin 문서 https://realm.io/docs/xamarin/latest/

72. 최신 모바일 기술은 Realm에서 https://realm.io

73. Thank you



...

반응형
반응형

[MSSQL] 세로 데이터 가로로 출력 (데이터 한줄로 출력) STUFF, FOR XML PATH


http://ggmouse.tistory.com/127




DECLARE @string AS VARCHAR(1000);

SET @string = '';

 

WITH TABLE_A (NAME) AS (

    SELECT '손꽁쥐' UNION ALL

    SELECT '윤선생' UNION ALL

    SELECT '황박사'

)

 

SELECT @string = NAME + ', ' + @string FROM TABLE_A

SELECT @string AS '가로출력' 




--  

WITH TABLE_A (CLASS, NAME) AS (

    SELECT 'A', '손꽁쥐' UNION ALL

    SELECT 'B', '윤선생' UNION ALL

    SELECT 'A', '황박사'

)

SELECT * FROM

(

    SELECT CLASS, STUFF((SELECT ',' + NAME FROM TABLE_A WHERE CLASS = A.CLASS FOR XML PATH('')), 1, 1, '') AS 'Result'

    FROM TABLE_A AS A

) A

GROUP BY A.CLASS, A.Result


반응형
반응형

'구글 스패너'···막 오르는 SQL 데이터베이스 새 시대 


 원문보기: http://www.ciokorea.com/news/34274


전통적인 데이터베이스를 확장할 때에는 일반적으로 샤딩(sharding)이라는 프로세스가 사용된다. 데이터를 여러 개의 소규모 데이터베이스로 쪼갬으로써 부하를 분산하는 방식이다. 2005년 당시에 애드워즈를 구동하는 데이터베이스는 샤딩을 한 번 다시 하려면 몇 년이 걸릴 정도로 방대해지고 있었다. 새로운 데이터베이스가 필요했고 구글은 직접 구축에 나섰다.


이처럼 구글이 애드워즈 처리를 위해 구축했던 데이터베이스가 스패너(Spanner)라는 제품으로 최근 일반에 공개됐다. 최근 새로운 데이터베이스들이 잇달아 출시되고 있는 가운데 스패너도 합류한 것이다. 최신의 데이터베이스들은 전통적인 관계형 SQL데이터베이스와 비슷하지만 방대한 규모로의 확장성은 훨씬 뛰어나다. 기존의 SQL에 새롭다는 의미의 형용사(New)를 결합해 NewSQL이라고 불리곤 한다.


데이터베이스 시장의 움직임을 주시하는 전문가들은 NewSQL 데이터베이스가 언젠가는 오라클, IBM, 마이크로소프트 등의 거물급 데이터베이스 제품들과 치열한 경쟁을 벌이게 될 것이라고 보고 있다.


스패너란 어떤 제품? 

구글의 스패너는 여러 요건을 충족시키기 위해 등장했다. 한편으로는 방대한 규모로 확장성이 필요했고 다른 한편으로는 전 세계 데이터센터로의 분산도 필요했다. 아울러, 구글은 데이터베이스 프로그래밍 언어의 대표격인 SQL을 사용하는 관계형 데이터베이스를 원했고 여기에 낮은 지연시간과 매우 높은 신뢰성이라는 조건도 추가했다. 구글은 10년 가까운 개발 노력 끝에 2012년 스패너와 이를 구글 내에서 이용한 사례를 소개한 연구 논문을 발표했다.


그 후 몇 년에 걸쳐 구글은 스패너를 자사 클라우드 플랫폼에서 제공되는 데이터베이스로 개발하는 작업을 진행했다. 마침내 올해 초 스패너의 초기 베타 버전이 등장했다.

스패너는 구글의 클라우드에 호스팅되는 분산형 데이터베이스로서 전 세계적인 일관성과 확장성이 특징이다. 이는 데이터 접근이 필요한 최종 사용자와 가깝게 데이터가 존재할 수 있도록 스패너의 인스턴스(instance)가 전 세계 곳곳에 위치할 수 있는 동시에 데이터베이스의 각 복사본은 동일하다는 것을 의미한다. 말은 쉽지만 결코 쉽지 않은 특징이다.


구글 클라우드 내에는 스패너 운용에 필수적인 두 가지 독특한 기능이 있다. 하나는 전 세계 데이터를 동기화 하기 위해 가장 정확한 시간 측정 방식인 원자 시계를 사용하는 트루타임(TrueTime)이라는 타임 스탬프(time-stamp) 기능이다.


다른 하나는 전 세계 구글 데이터센터를 연결하는 구글 내부 광섬유망이다. 스패너의 내부 데이터베이스 트래픽은 일반 인터넷 대신 구글에서 직접 구축하고 통제하는 구글 트래픽 전용 파이프를 통해 전송된다. 전 세계 어느 곳이든 연결되는 스패너 내부 트래픽 전용 고속도로가 있는 셈이다.


NewSQL 시장 

스패너는 클라우드에 호스팅되는 NewSQL 데이터베이스 중 최초로 광범위하게 사용될 것으로 여겨지는 제품 가운데 하나다. 카네기 멜론 대학교(Carnegie Mellon University) 앤드류 파블로 교수는 공동 논문에서 NewSQL에 대해 “지속적으로 발전되는 데이터베이스 기술의 다음 단계”라고 평가했다.


NewSQL 데이터베이스의 개별적인 특징은 새로울 것이 없지만 그 동안 이를 모두 아우르는 데이터베이스는 없었다. 예컨대, 전통적인 관계형 데이터베이스는 SQL를 지원하고 일관성이 강한 반면 확장성이 부족하고 NoSQL 데이터베이스는 확장이 쉬운 반면 SQL 지원이 부족한 단점이 있다.


위 논문에서는 NewSQL 데이터베이스에 대해 “분산된 컴퓨팅 리소스가 풍부하고 저렴한 동시에 응용프로그램의 요구사항은 훨씬 더 커진 새로운 시대가 낳은 산물”이라고 표현했다.


이렇게 새로운 세대의 데이터베이스의 시장은 아직 시작 단계다. NewSQL 데이터베이스 중 가장 주목할 만한 예로는 인메모리(in-memory) 관계형 데이터베이스인 SAP 하나(HANA)를 들 수 있다. 이 밖에도 몇몇 신규업체에서 NuoDB, H-Store, Clusterix, VoltDB, MemSQL 등의 NewSQL을 선보이고 있다.


이 밖에 아마존 웹 서비스의 아마존 오로라(Amazon Aurora)가 MySQL 및 PostreSOL이 지원함에 따라 NewSQL의 일종으로 간주되기도 한다.


NewSQL 데이터베이스의 장점 중 하나는 전통적인 SQL데이터베이스에서 실행되는 응용프로그램이 지원된다는 점이다. 그러나 위 논문 저자들은 그러한 전통적인 데이터베이스에서 실행되는 작업은 보통 핵심 응용프로그램이므로 기업들은 강력한 요인이 없는 한 이를 새로운 데이터베이스로 이동하기를 꺼릴 것이라고 지적했다.


NoSQL 데이터베이스는 확장성이 뛰어나며 소셜, 모바일, 사물 인터넷 응용프로그램을 중심으로 하는 새로운 응용프로그램에 주로 사용될 전망이다. 


NewSQL 시장의 움직임을 주시하는 애널리스트들은 향후 몇 년간 무난한 성장할 것으로 낙관하고 있다. 마켓 어낼리시스(Market Analysis)에서는 NewSQL 데이터베이스 시장이 복합 성장률 26%을 기록하여 2020년까지 10억 달러 규모에 이를 것으로 예측하고 있다.


이는 IDC에서 연간 300억 달러 이상으로 보고 있는 전통적인 관계형 데이터 관리 시장 규모에 비하면 미미한 수준이다. 그러나 전통적인 데이터베이스에 고충을 겪고 있는 고객들이라면 새로운 작업을 위해 기꺼이 NewSQL에 투자할 것이라는 의미이기도 하다.




.


반응형
반응형

Microsoft SQL Server Management Studio Express

SSMSE(Microsoft SQL Server Management Studio Express)는 SQL Server 2005 Express Edition 및 SQL Server 2005 Express Edition with Advanced Services를 관리할 수 있는 사용이 용이한 무료 그래픽 관리 도구입니다.


63비트 다운로드 후 관리자권한 으로 실행. 


https://www.microsoft.com/ko-kr/download/details.aspx?id=8961







.

반응형
반응형

MySQL 클론의 역습 – 1 (MariaDB 편)  https://mariadb.org/


https://embian.wordpress.com/2013/06/26/mysql-%ED%81%B4%EB%A1%A0%EC%9D%98-%EC%97%AD%EC%8A%B5-1-mariadb-%ED%8E%B8/


사실 이 글의 제목을 처음에는 “MySQL의 형제들” 이었다.


source가 fork된것이니 형제보다는 부모 자식 관계가 더 맞지 않을까 생각되서, “MySQL의 자식들”이라고 제목을 바꾸었다가 어감이 좋지 않아서 MySQL의 창시자가 자신의 첫째딸 이름을 따서 MySQL이라고 작명한 것에 착안해 “MySQL의 딸들”이라고 바꾸었다.


그런데, 그만 코드가 복제되서 다시 분화된 것인데 이것을 부모 자식간이라고 해야 하나 형제간이라고 해야 하나 쓸데없는 고민에 빠져버렸다.


결국, 장고 끝에 제목은 “MySQL 클론의 역습”이라고 결정했다. (그런데 실제로 MySQL과 클론들끼리 정말 싸우지는 않는다. 심지어 그들 간은 사이가 좋아 보이기 까지 한다.)


헛소리는 여기까지 하고 본문으로 들어가 보자. ^^;


우리나라에서 DB라고 하면 Oracle 아니면, MySQL이다. 특히 웹서비스 환경은 MySQL이 현재까지도 대세라고 할 수 있다.


최근들어 NoSQL이니 BigData니 하는 새로운 페러다임과 프로그램들이 등장하면서 광풍의 조짐이 보이고는 있지만, 여전히 사용함에 있어서는 제한적이고 진입장벽이 만만치가 않다.


아직까지 DB의 메인스트림은 RDBMS이고, 새로운 웹 프로젝트가 진행되면, 당연하듯 DBMS로는 MySQL이 거론되곤 한다.


사실 좀 지루했었다.


뭔가 MySQL이 아닌 새로운 것을 만지고 싶었을 뿐이었다.


그래서 어떤 프로젝트에서 Postfix를 도입해 볼까 하다가 MySQL에 익숙한 엔지니어들과 개발자들의 반대에 부딛혀야 했고,  본인 스스로도 딱히 그 프로젝트에서 Postfix를 써야 할 당위성을 찾기도 힘들어서 포기한적이 있다.


최근 모바일 게임 관련 프로젝트를 진행하면서 MySQL에서 fork된 몇가지 DBMS들을 만져볼 수 있게 되었다. 이해 당사자도 적고, 약간 도전적인 프로젝트이다 보니 아무런 태클 없이 혼자서 자유롭게 DBMS를 선택할 수 있는 기회였다.


이 글은  그 때 research 했던 MySQL fork program 들에 대한 간단한 소개 글이다.


MySQL이 Oracle에 편입된 후, MySQL의 향후 운명에 대한 우려의 목소리가 많아졌다.


이러한 우려 속에서 MySQL의 대안을 찾으려는 움직임이 많아지고 있는데, 그것들 중 대표적인 것으로 MySQL에서 fork된 프로젝트들을 꼽고 싶다.


이 글에서는 MySQL fork 프로젝트들 중 가장 많이 알려진 세가지 프로젝트에 대해서 정리 하려고 한다.


1. MariaDB


MariaDB 의 주요 개발자는 Michael Monty Widenius라는 사람으로 MySQL을 개발했던 사람이고, 그 MySQL을 Sun에 10억 달러(약 1조원)에 매각하면서 핀란드 10대 부자중 한 명이 된 사람이기도 하다.


하지만 MySQL을 인수했던 Sun이 다시 Oracle로 인수되자, Monty Program AB이라는 회사를 설립하고 MySQL의 소스를 기반으로 MySQL과 완벽하게 호환이 되는 DBMS를 개발 하는데, 이것이 MariaDB이다.


MySQL, MariaDB 둘 다 Monty의 딸 이름을 따서 만들었는데 MySQL은 첫째 딸, MariaDB는 둘째딸의 이름에서 따론 것이라고 한다.(딸바보인가보다)


MariaDB는 MySQL의 소스를 가져다 만들기도 했지만, 목표자체가 MySQL을 완벽하게 대체하는 것이다 보니, 기존 MySQL과 완벽하게 호환이 된다.


프로그램의 룩앤필도 거의 똑같고 지원하는 함수들도 모두 일치하며 심지어 파일 이름들도 그대로 MySQL의 것을 가져다 쓰고 있다.


개발자들이 그냥 보기에는 이게 MariaDB인지 MySQL인지 모를 정도이다. (Client의 프롬프트가 “MariaDB” 로 뜨는 것 말고는 정말 똑같다.)


당연히 php-mysql 이라던지, jdbc-mysql-connector같은 기존 db connection library도 그대로 사용할 수 있기 때문에 실제로 개발자들은 MySQL에서 MariaDB로 DB 서버가 바뀐다고 해도 전혀 소스코드 수정이 필요없으며, 추가적인 DBMS에 대한 학습도 거의 필요가 없다.


즉, MySQL을 다룰줄 아는 개발자라면 MariaDB의 진입장벽은 거의 없는 수준이라고 할 수 있다.


하지만, MySQL을 완벽하게 대체한다는 사실만으로 기존에 MySQL을 잘 사용하던 사람들이 막연한 불안감이나 새로운 프로그램에 대한 단순한 호기심만으로 MariaDB로 갈아타지는 않을 것이다.


그럼 MySQL 대신 MariaDB를 썼을 때 얻을 수 있는 잇점들은 어떤 것이 있을까?


첫번째 장점은 월등히(?) 빠른 쿼리 타임을 들 수 있다.


인터넷이 돌아다니는 다양한 퍼포먼스 테스트 결과를 보면 전반적인 쿼리 성능이 MySQL에 비해 좋은 것을 알 수 있다.


특히, sub query나 join query 같은 경우 따로 MariaDB의 특징으로 소개할 만큼 성능 향상이 있다.


그리고 본인이 직접 테스트한 결과에서는 Partitioning table에 대한 select 쿼리 결과가 특히 눈길을 끌었는데, 자세한 테스트한 결과는 따로 추가 글을 작성할 예정이다.


두번째 장점은 다양한 추가 기능들이다.


이 글에서는 다양한 추가 기능들중 몇가지만 소개하고자 한다.


1. Microseconds in MariaDB


테이블을 생성할 때 시간관련 자료형에 정밀도를 설정 할 수 있다.


CREATE TABLE example(


col_microsec DATETIME(6),


col_millisec TIME(3)


);


정밀도는 0부터 6까지 설정할 수 있으며, 설정된 값만큼의 microseconds가 출력된다.


SELECT CURTIME(4);


–>10:11:12.3456


2. Microseconds Precision Processlist


INFORMATION_SCHEMA.PROCESSLIST 테이블에 TIME_MS 컬럼이 추가 되었다.


processlist를 볼때 MySQL에서는 실행타임이 초단위까지 밖에 나오지 않았다면 MariaDB에서는 microseconds 단위까지 확인 할 수 있다.


3. Table Elimination


여러개의 table 조인으로 구성된 쿼리의 경우, 사용하기 편하기 view table을 따로 구성하기도 하는데, view table에서 특정 컬럼을 select할 경우 실제로 조인된 table들중 쿼리에 필요 없는 테이블이 발생할 수 있다.


MariaDB는 이런 경우 자동으로 쿼리에 필요 없는 테이블을 조인쿼리에서 제거해주는 기능을 가지고 있다. (이 특징은 성능 향상쪽에 가까운것 같기도 하다.)


4. Virtual Column


다음의 테이블 스키마를 보자.


create table table1 (


-> a int not null,


-> b varchar(32),


-> c int as (a mod 10) virtual,


-> d varchar(5) as (left(b,5)) persistent);


table1의 c 컬럼은 가상컬럼이다. 실제로 storage에 저장되지 않고 query 실행시간에 계산되어 출력된다.


table1의 d 컬럼은 실제로 storage에 저장이 되는 가상컬럼으로, insert나 update 때 계산되어 저장 되는 컬럼이다.


더 많은 추가 기능들이 있는데, 추가기능에 대한 설명은 여기에서 확인 할 수 있다.


한가지 주의할 점은 MariaDB의 추가 기능들을 사용할 경우 혹시라도 부득이하게 MySQL로 돌아가야 될 경우 호환이 안될 수도 있다는 점을 유의해야 한다.


마지막으로 MariaDB는 다양한 Storage Engine을 지원한다.


1. Aria


Aria 엔진은 MyISAM과 호환되면서 추가적으로 Transactional기능이 추가된 Engine이다.


2. XtraDB


InnoDB의 대체 Engine으로 다음에 설명할 Percona사에서 개발한 Storage Engine이다.


3. PBXT


일반적인 목적의 transactional storage engine으로 현재 더이상 maintaine 되지 않고 있어서 MariaDB에 기본 탑제되어 있지 않지만, 필요한 경우 재컴파일을 통해 사용할 수 있다.


4. FederatedX


Federated Storage Engine의 fork engine으로 Federated engine은 원격 서버의 table에 접근해서 Insert, Update, Delete, Select 를 할 수 있도록 해주는 engine이다.


5. OQGRAPH


Open Query Graph storage engine의 약자로 트리나 그래프 형태로 출력될 수 있도록 데이터를 저장하는 engine이다.


6. IBMDB2I


MySQL 5.1.55에서 빠졌던 엔진인데, MariaDB에서는 아직까지 지원하고 있다.


7. SphinxSE


Full Text Search Engine 으로 Full Text Search가 필요한 경우 사용할 수 있을 듯 하다.


8. Cassandra in MariaDB-10.0


NoSQL DBMS인 Cassandra cluster에 MariaDB를 통해 접근 할 수 있도록 10.0 버전에 추가되었다.


3가지 측면에서 MariaDB의 장점에 대해서 설명했는데, 개인적으로는 첫번째 장점인 성능 향상 만으로도 MariaDB를 쓰는 이유는 충분한 것 같다.


본인 입장에서는 추가 기능의 필요성은 아직까지 피부로 와닿지 않았고, 추후 MySQL이나 Percona로 전환해야 될지도 모르는 이슈 때문에 전혀 고려대상이 되지는 못했다.



.

반응형
반응형

Tadpole DB HUB 개발자 가이드  :  https://github.com/hangum/TadpoleForDBTools

올챙이는 웹 기반 DB 관리 도구입니다. 웹 브라우저에서 올챙이를 통해 다양한 DB로 접속할 수 있고, 권한을 조절 할 수 있습니다. 올챙이의 최종 지향은 DB HUB 입니다.

목차


반응형

+ Recent posts