오랫동안 윈도 10으로 업글해서 썼던 본인의 데스크탑PC가 자꾸, 블루스크린이 나오고 자동 에러 복구가 안되어서

스트레스가 이만저만이 아니었다.

 

SSD불량일까 싶어, chkdsk도 돌리고 이것저것 다해보았지만 아무짝에도 소용없었다.

 

본인의 PC는 요즘 흔한 UFEI방식의 부팅을 지원하지도 않고, USB부팅도 안된다. 오래된 DVD RW가 EIDE방식으로

물려있고 해서, 마이크로소프트에서 윈도10 ISO파일을 구해와 DVD로 굽고 에러복구나 재설치를 해봐도 잘 안되었다.

 

 

다른 방식을 찾아서 DVD도 안되고 USB부팅도 안되었을때는 하드설치 밖에 더 있을까 고민하여 구글링을 한 결과

국내의 유명한 IT블러거이신 스누피박스 님의 제목그대로의 "윈도 10 하드디스크 설치하기" 를 참고해서(스누피님은

부팅매니저 cmd파일을 손수 만드신 듯 했다. ) 그대로 따라해봤는데,

 

여기에는 제한이 있었다. 이미 윈도 10 이하의 버전이 돌아가는 PC에서 하드디스크를 파티션하여, 하드파티션

디스크에 셋업 부팅매니저를 심는(?) 방식이라, 멀티 부팅 셋업방식이라고 보면 된다. 파티션을 나누지 않고 지금 쓰고

있는 PC하드디스크에 재설치를 하려면, 하드디스크 자체에 설치부팅이 돌아가야 한다.  이런 방식은 안되어 있어서

 

다시 구글링을 한 결과, 외국사이트에서 이러저러한 내용이 나와있어서 그대로 따라했더니 설치가 잘되었다.

 

그래서 아래는 그 설치방식을 공유하고자 한다.  아래내용에 대해 혹시 일어날지 모르는 데이터 피해에 대해서는

절대 책임을 안지니, 본인 스스로 책임 결정하기 바란다

 

1. 윈도10설치디스크 ISO를 풀어서 설치파일을 통째로 설치하려는 하드디스크에 복사한다.

 

2. 설치하려는 하드디스크를 다른 PC에 붙여서, 다른 PC에서 관리자 명령창을 열어서 다음과 같이 한다

 

c:\ diskpart  [엔터]

[diskpart] list disk [엔터]  <== 윈도10을 설치하려는 디스크의 넘버(#)를 파악한다 0부터 시작

[diskpart] select disk [디스크넘버] [엔터] <== 디스크넘버가 0이라면 select disk 0

[diskpart] list partition  [엔터] <== 선택된 디스크의 파티션 넘버(#) 가 나열된다.

[diskpart] select partition [파티션넘버] [엔터] <== 부팅을 활성화할 넘버를 선택한다. select partition 0

[diskpart] active [엔터] <== 활성화시킨다

[diskpart] exit [엔터] <== 나가기

 

 

3. 부팅매니저를 탑재한다.

    설치 DVD롬에서 할 수도 있고,  설치ISO를 푼 파일에서 해도 된다.

 

x:\boot\bootsect.exe /nt60 E:   <== x드라이브는 설치DVD 디스크명이거나 설치파일 디스크명이고, E: 가 설치할 디스크명이다.

 

4. 설치할 하드디스크를 PC에 장착해서 부팅하면, 자동으로 윈도 10 설치모드가 진행된다

5. 정상 설치하면 됨..

 

 

 

 

회계 용어 중의 하나 정의는 다음과 같다.

 

알아두면 요긴하게 의미소통이 가능하다고 봄

 

 

상계 : 지급할 돈과 받을 돈을 서로 상쇄하여 소멸하는 것.

 

---> 상계처리한다 : 예) 내가 가게를 운영한다면, 고객이 물건을 구입하여 카드를 긁고 나면 승인이 처리되고(여기서 승인처리란 가결제 비슷한 것임, 카드사가 보증을 해줘서 거래대금을 지불한 것으로 결제승인이다) 물건대금을 받은 것으로 하여 물건을 인도한다(판다).  그런 거래(승인트랜잭션)가 일어나고 나서 하루나 이틀 후에 카드사의 거래건매입이 일어난다. 매입이란 실제 그 거래건을 카드사가 사들이는 행위로 거래대금(현금)을 카드사로 부터 지불결정된 일을 말한다.  이런 시퀀스가 계속 진행되는데, 예외적인 경우로, 고객이 신용카드 승인을 한 이후 1주일쯤 지나서 카드취소를 하는 경우가 있다. 이때 매입뿐만 아니라, 가맹점에 대금 입금이 완료된 상태라면 앞으로 지급할 가맹점 대금에서 취소대금을 차감해서 취소하는 서비스를 말한다.  그러니까,  그 고객이 취소한 신용카드 거래건이 이미 가맹점에 대금입금이 되었으므로, 앞으로 가맹점 매출로 카드사가 대금입금할 금액을 상쇄하여 소멸시키는 행위를 말한다.

 

 

계상: 예산을 편성할 때, 어떤 내용을 넣는 일

 

---> 예산항목에 넣는 것을 말한다. 앞으로 이런 항목으로 돈 들어갈 일이 있는 것을 새롭게 추가하는 것을 말한다.

아내가 프로그래머 남편에게 심부름을 시키며 말했다.

"우유 하나 사와. 아, 계란 있으면 여섯 개 사와."

남편은 잠시 후, 우유를 여섯 개 사왔다.

아내가 물었다. "왜 우유를 여섯 개나 사왔어!"

남편이 말했다. "계란이 있길래 여섯 개 사왔지."

--인터넷 유머

IQ 쑥쑥 올리는 생활 속 실천 31
독서를 많이 하고 외국어를 익혀라.
체스를 배우고 가끔씩 멍해져라.
더 큰 두뇌를 얻기는 생각보다 더 쉽고 재미 있다



1. 단어완성 게임을 즐겨라.
할리우드 스타 알렉 볼드윈은 이륙 전 기내에서 휴대전화를 끄라는 승무원의 지시를 어기고 스마트폰으로 ‘워즈 위드 프렌즈’라는 낱말완성 게임을 하다가 쫓겨났다. 연구 결과에 따르면 단어완성 게임이 알츠하이머와 치매 위험을 낮춰주는 데 도움이 될지 모른다. 따라서 인기 스마트폰으로 시간을 보낸다고 죄책감을 가질 필요는 없다. 비행기를 탈 때 꺼야 한다는 점만 기억하라.

2. 강황을 섭취하라.
인도와 태국 커리에 사용되는 강황에는 치매 위험을 낮춰줄지 모르는 커큐민이 들어 있다. 인도에서는 강황이 치자색 염료로도 사용된다.

3. 태권도를 배워라.
아니면 댄스나 스쿼시를 하라. 심박 수를 높이고 다양한 기능의 조정이 필요한 활동을 택하라고 ‘획기적인 운동과 두뇌의 신과학(Spark: The Revolutionary New Science of Exercise and the Brain)’을 쓴 존 레이티가 말했다. 외출을 싫어하는 사람이라면 마이크로소프트의 키넥트(Kinect)나 닌텐도의 위핏(Wii Fit) 같은 쌍방향 게임으로 뇌 운동을 할 수 있다.

4. 알자지라 방송을 보라.
2009년의 연구에 따르면 알자지라 TV의 영어 방송을 시청한 사람들이 CNN 인터내셔널이나 BBC 월드에서 뉴스를 듣는 사람보다 더 열린 마음을 가졌다.

5. 스마트폰을 던져버려라.
e-메일을 끊임없이 확인하면 집중력이 떨어지고 생산성이 저하된다.
당면 과제에 집중하도록 해주는 인터넷 차단 소프트웨어
‘프리덤(Freedom)’을 설치해 가끔씩 오프라인 상태를 즐겨라.

6.잠을 충분히 자라.
낮잠을 자고 일찍 잠자리에 들어라. 하버드대 연구에 따르면
잠을 자는 동안에도 우리의 뇌는 기억 정보를 계속 처리한다.
잠은 필요한 정보를 나중에 더 잘 끄집어 낼 수 있도록 해준다.

7. TED 앱(응용프로그램)을 내려 받아라.
연례 TED(기술, 오락, 디자인) 대회는 세계적인 명사들이 뇌매핑(brain mapping)과 태아 지능(prenatal intelligence) 같은 첨단 문제를 탐구하는 지식 공유의 장이다. 참석이 어렵다면 iOS나 안드로이드용 TED 앱을 내려받아 스마트폰에 설치하라.

8. 문학 축제에 참석하라.
미국의 로스앤젤레스, 영국의 웨일스, 인도의 자이푸르를 늘 가보고 싶었다고? 주요 연례 도서 축제가 열리는 곳들이다. 축제에 맞춰 비행기표를 구입해 여행을 즐기면서 톰 스토파드(영국 극작가)나 제니퍼 이건(미국 소설가) 같은 문인들에게서 한수 배워보는 게 어떨까?

9. ‘기억의 궁전’을 지어라.
기억을 신속히 되살리는 비결은 기억하고 싶은 것을 생생한 이미지와 연관짓는 것이다. 대다수는 ‘기억의 궁전(마음의 공간이 이미지를 저장하는 기법)’을 지을 인내심이 없을지 모른다. 그러나 적어도 조슈아 포어의 ‘아인슈타인과 문워킹을(Moonwalking With Einstein: The Art and Science of Remembering Everything)’을 읽어 그런 기법의 감을 잡으면 도움이 된다.

10. 외국어를 배워라.
외국어를 배우면 전전두피질의 활동이 강화된다. 전전두피질은 의사결정과 감정을 관장하는 뇌 부위다. 외국어 강습에 등록하거나, 중국 스촨성 오지에 직접 가서 중국어를 배우거나, 외국어 학습 소프트웨어 로제타 스톤으로 라틴어를 자습하라.

11. 다크 초컬릿을 먹어라.
물론 그런다고 IQ가 하루 아침에 높아지지는 않는다. 하지만 다크 초컬릿은 기억력을 높인다고 알려진 플라보노이드를 함유한다. 레드 와인 한 잔을 곁들이면 금상첨화다. 레드 와인에도 플라보노이드가 많다.

12. 뜨개질 동아리에 가입하라.
뜨개질로 멋진 스카프를 만들어 보라. 운동 기능을 단련하면 인지 기술이 강화될 수 있다. 아울러 올 겨울을 따뜻하게 날 수도 있다.

13. 미소를 자제하라.
실험에 따르면 얼굴을 찌푸리는 간단한 행동도 당면 사안을 회의적으로 보면서 더 깊이 분석적으로 사고하게 만든다.

14. 폭력적인 비디오게임을 하라
.무슨 소리냐고? 말 그대로다. 여러 연구에 따르면 비디오게임이
신속한 반응을 촉진하며, 한꺼번에 여러 가지 일을 처리하는 능력을 키워주고, 스트레스 많은 과제를 끝낸 뒤 적대감을 완화시켜준다. 따라서 이번 겨울의 인기 게임을 살펴 보라.

15. 이런 사람들을 트위터로 팔로하라.
누리엘 루비니(@Nouriel): 그에게서 경제학적 통찰력을 얻고 페이스북에서 그의 플레이보이 생활을 보여주는 사진을 구경하라. 자드 아붐라드(@JadAbumrad): 그의 ‘라디오랩(Radiolab)’ 프로그램은 라디오 방송에서 과학과 철학의 가장 멋진 안내자다. 콜슨 화이트헤드(@colsonwhitehead): 유명한 소설가로 140자 단문에서도 통찰력과 재미를 선사한다.

16. 요거트를 즐겨라.
생균 식품은 원래 소화에 좋지만 생쥐 연구에 따르면 뇌에도 좋다. 요거트를 먹은 생쥐는 불안감에 더 잘 대처하며 감정과 기억을 관장하는 뇌 부위의 활동이 증가했다.

17. ‘수퍼메모(SuperMemo)’를 설치하라.
무엇인가를 기억하고 싶다면 잊기 직전에 상기하는 방법이 최고다. 플래시카드 암기 소프트웨어인 수퍼메모는 중요한 새로운 데이터를 분류해서 정리한 다음 잊기 직전에 기억하도록 상기시켜준다.

18. 셰익스피어 연극을 관람하라.
연구에 따르면 셰익스피어 작품을 읽으면 대다수 현대 작품을 읽을 때보다 뇌가 더 활발해진다. 하지만 연극으로 그의 작품을 구경해도 도움이 된다. 올 겨울 뉴욕시에선 ‘티투스 안드로니쿠스’가, 워싱턴에선 ‘베로나의 두 신사’가 무대에 오른다.

19. 생각에 공을 들여라.
‘생각, 빠르고 느림(Thinking, Fast and Slow)’의 저자 대니얼 카너먼에 따르면 사고에는 두 가지 방식이 있다. 시스템1은 빠르고 자동적이다. 시스템2는 느리고 의식적인 노력이 든다. 이 두 방식을 이해하면 더 나은 사고와 선택을 할 수 있다고 카너먼은 주장했다.

20. 물을 많이 마셔라.
의사와 트레이너들이 늘 그렇게 말하지만 뇌 강화에도 물이 필요하다. 탈수가 되면 뇌의 활동에 에너지가 더 많이 소모되며 기획 능력을 저하시킬 수 있다.

21. 아이튠스U(iTunes U)에서 강의를 들어라.
살지 않는다고 해도 얼마든지 아이비리그의 수업을 청강할 수 있다. 애플이 아이튠스에서 제공하는 학습콘텐트 아이튠스U는 고대 철학에서 천체물리학까지 다양한 과목의 명문대 강의를 온라인으로 들을 수 있다.

22. 미술관을 방문하라.
미술관을 찾는 사람이 멋져 보이기도 하지만 연구에 따르면 미술작품 감상은 스트레스를 완화해 진정으로 중요한 사안에 집중하게 해준다. 테이트 모던 갤러리의 ‘대미언 허스트전’(4월 4일까지)이나 뉴욕현대미술관에서 열리는 ‘신디 셔먼전’(2월 26일까지)이 볼만하다.

23. 악기를 연주하라.
기타 줄을 튕기거나 피아노 건반을 두드려라. 악기 연주법을 배우면 IQ가 높아지며 기억과 조정을 관장하는 뇌 부위의 활동이 증가한다.

24.필기를 하라.
손으로 글을 쓰는 느낌을 기억하는가? 아마 가물가물할 것이다.
뇌 촬영 영상을 보면 타이핑을 할 때보다 필기를 할 때 뇌의 더 많은 부분이 활성화된다. 덤으로 기억력도 좋아진다.
종이에 적으면 기억하기가 더 쉽다.

25. 포모도로(pomodoro) 테크닉
파스타가 아니라 주방에서 쉽게 볼 수 있는 토마토 모양의 타이머를 활용한 시간관리법을 말한다. 25분씩 단위를 정해 한 가지 일에 집중하도록 도와준다. 사이 사이에 쉬는 시간이 잦아 정신적 민첩함을 유지하는 데도 도움이 된다.

26. 가끔 생각을 비워라.
멍한 상태로 있으면 뇌에 도움이 된다. 여러 연구에 따르면 의식하지 않고 아무 생각을 하지 않으면 뇌가 ‘큰 그림’의 사고를 할 수 있다.

27. 커피를 마셔라.
한 컵으로는 부족할지 모른다. 하루 커피 4잔을 마신 여성들이 한 주에 한 컵을 마신 여성들보다 우울증에 시달릴 확률이 낮았다. 카페인이 단기기억에 도움이 된다는 연구 결과도 있다.

28. 만족을 지연시켜라.
앞에 놓인 마시맬로를 즉시 먹지 않고 참은 아이들이 바로 먹어치운 아이들보다 수년 뒤 시험점수가 더 높았다는 유명한 연구 결과가 있다. 그런 아이들이 반드시 선천적으로 인내심이 많지는 않았다. 다만 그들은 다른 활동에 집중해서 욕구 충족을 지연시켰다.

29. 전문가가 되라.
진정으로 즐기는 한가지 일을 계속 반복해 숙달하면 그 일을 할 때 뇌가 더 효율적으로 작동한다. 예를 들어 체스 천재들은 아마추어보다 패턴을 더 빨리 인식한다. 전문 기술은 타고나는 게 아니다. 옛 속담처럼 연습이 완벽한 기술을 가져다준다.

30. 온라인 댓글을 달아라.
인터넷에선 누구나 비평가가 될 수 있다. 무언가를 좋아하거나 싫어할 때 아마존이나 옐프 등 어느 사이트에서든 비평의 글을 올려라. 자신의 견해를 글로 표현하는 동안 자신의 생각을 더 잘 이해하게 된다.

31. 도시를 벗어나라.
과학 전문 언론인 조나 레러에 따르면 대도시의 삶은 주의를 산만하게 만든다. 번잡한 도로에서 몇 분만 있어도 기억력과 자제력이 떨어진다. 뇌가 그 모든 자극을 처리해야 하기 때문이다. 주말에 호젓한 곳을 찾아 자연과 교감하면 뇌의 기능 회복에 도움이 된다.

김정선의 SQL Server 이야기
차집합 구하기, 어떤 쿼리가 좋을까?

 

 

 

김정선(jskim@feelanet.com)

필라넷 DB사업부 수석컨설턴트

SQLServer 아카데미/트라이콤 교육센터 강사

 

Microsoft SQL Server MVP

MCT/MCITP/MCDBA

 

 

 

 

차집합(Difference of Sets)

두 집합 A, B를 생각할 때, A에 속하고 B에는 속하지 않는 원소로 구성된 집합을 A에 대한 B의 차집합이라하고, A-B로 표시하며 흔히 벤 다이어그램으로 나타낸다.

 

 

 

이번에 좀 쉬운 내용으로 정했습니다 ^^

 

차집합을 구하라

 

주문이 없는 제품을 구하라!”,

거래가 없는 고객을 구하라!”,

미발송된 주문 상세 내역을 구하라!”

 

차집합과 유사한 성격의 결과 집합을 도출하는 쿼리를 가끔 작성하게 됩니다. 이 때, 가장 큰 문제 중의 하나는 바로 쿼리 성능 문제입니다. 수행되는 집합 연산의 성격 상 모델 변경 없이 쿼리 만으로 좋은 성능을 만들기란 쉽지가 않습니다. 대량 범위의 데이터에서는 더 큰 문제를 내포하게 됩니다. 그런데, 현장에서 만들어진 쿼리를 보면 LEFT OUTER 조인과 같은 가장 나쁜 쿼리 유형을 선택해서 사용하고 있는 것을 자주 보게 됩니다. SQL Server 관련 Q/A에서도 많이 볼 수 있는 질문 유형 중의 하나였습니다.

 

언젠가는 한 번 비교를 해 보고 그 결과를 많은 개발자 혹은 DBA들과 공유하자 마음 먹고 있었습니다. 또한 다른 분들의 좋은 솔루션이나 의견도 듣고 싶었습니다. 얼마 전 SQL 전문 Blog에 관련된 글이 올라온 것을 보고 그 기억을 되살리게 되었고, 이제서야 잠깐 짬을 내 기본적인 쿼리 유형들을 샘플로 간단히 만들고 이를 비교한 내용들을 기록합니다. 특히, SQL Server 2005 Query Optimizer에서 이전 버전과 두드러진 한 가지 차이점을 공통적으로 보이고 있어서 재미 있는 이슈가 될 듯 합니다. 이 또한 예제에 포함시켜 두었습니다.

 

간단한 예제들이지만, 차집합 성격의 결과 집합 도출 시 어떤 쿼리 유형들이 가능할지 그 선택 범위를 살펴보고 다양한 상황에 따라 적절한 접근 방법으로 활용하면 도움이 될 것이라 판단됩니다. 특히, 막연히 LEFT OUTER 조인만을 사용했던 경험이 있다면 이를 개선할 수 있는 다른 접근 방법들을 살펴볼 수 있을 겁니다.

 

 

쿼리 유형별 예제

 

LEFT OUTER JOIN 방식을 포함해서 쉽게 사용할 수 있는 몇 가지 예제 쿼리들을 다루고자 합니다. 각 유형별로 실행 계획과 I/O(실행 계획 이미지 하단에 포함)를 함께 표시하고 그 특징을 간단히 소개합니다. 설명을 통해 특징과 차이점을 알 수 있습니다. 특히, 몇 가지 쿼리에 대해서는 SQL Server 2000버전과의 큰 차이점을 하나 보여줍니다. 이 또한 정리해 두었습니다. 아래에서 살펴보시기 바랍니다.

 

1. NOT IN

2. NOT IN + 상관서브쿼리

3. NOT IN + 상관서브쿼리+ TOP 1

4. NOT EXISTS + 상관서브쿼리+ TOP 1

5. 상관 서브쿼리+ TOP 1 + IS NULL

6. OUTER JOIN + IS NULL

7. OUTER APPLY + IS NULL (SQL Server 2005 해당)

8. EXCEPT + (생략됨) 서브쿼리(혹은JOIN) (SQL Server 2005 해당)

 

참고. A, B 두 집합은 각각 Northwind Customers(91), Orders(830) 테이블로, 결과 집합은 주문(거래)이 없는 고객 집합을 도출하는 것을 예제로 합니다.

 

 

1. NOT IN

가장 간단하고 기본적인 유형입니다. 서브 쿼리의 결과 집합이 중복 값을 허용하지만 SQL Server Query Optimizer가 제공하는 최적화 전략 중 하나인 Constant Folding으로 인해 DISTINCT를 해 주지 않아도 됩니다. 아래 실행 계획은 오른쪽이 잘려 있는 상태입니다. 쿼리와는 달리 계획은 꽤 복잡한 형태를 띠고 있습니다. 부가적인Sort Merge 연산자를 동반하며, 내부 Nested Loop 조인으로 인해 실제 I/O는 매우 많은 검색 수(182)와 읽기 수(364)를 보여주고 있으므로, 성능이 좋지 않습니다. Bad!

 

 

 

 

 


 

 

 

2. NOT IN + 상관 서브쿼리

서브 쿼리를 상관 서브쿼리로 변경, 쿼리 상에서 직접적으로 Orders테이블과의 조인 관계를 제한했다. 그 결과, 조인 연산자를 Nested Loop 조인으로 선택했을 때의 과도한 I/O를 해결하기 위한 대체 방안으로 Merge Join을 선택하고 있다. 한 번의 검색(1)으로 각 테이블을 액세스하고 그 결과를 Merge 물리적 연산자로 처리하며, 논리적으로는 차집합에 해당하는Anti Semi 조인으로 해결하고 있다. Merge 조인을 위해서는 조인 키에 Clustered Index Covering Index를 요구하는데 두 테이블이 각각 이를 만족하는 상황이므로, Query Optimizer가 손쉽게 Merge 조인을 선택할 수 있다. 빠른 응답 속도는 아니지만 결과론적으로 I/O는 최소화되었다. 그럼 좋아진 것일까? 문제는 Merge를 하기 위해서 Index Scan을 하느라 전체 데이터를 액세스하고 있다. 불필요한 데이터를 액세스하지 않는다는 기본 쿼리 작성 규칙에 위반되므로 좋다고도 볼 수는 없다. 따라서 Not bad!

 

 

 

 

 

 

 


 

 

 

3. NOT IN + 상관서브쿼리+ TOP 1

저는 개인적으로 데이터 존재여부를 체크하는 서브 쿼리 유형에서 TOP 1 사용을 즐겨 합니다. 이는 교과서적인 내용이 전혀 아니지만, 컨설팅 경험을 통해서 인지하게 된 SQL Server Query Optimizer의 중요 특성 중의 하나입니다. 2번의 결과와 비교해 보면, 서브 쿼리 내 TOP 1을 추가한 것으로 쿼리 실행 계획의 큰 변화가 나타납니다. Query Optimizer Merge 조인 대신 Nested Loop 조인을 선택한 것입니다. 여기서 관심 있게 볼 부분은, 내부 입력인 Orders 테이블에 대해서는 Index Seek/Top/Filter 연산자의 순서입니다. 모든 검색 제한 조건을 처리한 후 Nested Loop 조인에 참여하고 있는 부분입니다. 이를 통해 반복적인 랜덤 I/O를 줄이게 됩니다.

 

이 방법은 실제로 김정선이 매우 즐겨 하는 서브쿼리 튜닝 전략 중의 하나입니다 ^^*

크게 2가지 목적을 달성하는 것입니다. 첫 번째는 조인 순서를 외부 쿼리에서 서브 쿼리로 풀리도록 강제하는 것이고, 두 번째는 Nested Loop 조인을 선택하도록 도와주는 것입니다. 이유는 Merge 조인과 같은 Stop-And-Go 방식의 연산자보다 Nested Loop 조인과 같은 Stream 방식이 훨씬 응답 속도(Response Time)가 빠르기 때문입니다. RDBMS는 일반적으로 OLTP성 쿼리로 주로 사용되며 OLTP는 쿼리 응답 속도가 제일 목표라는 사실 때문입니다. 상대적으로I/O가 커져 보이지만, 이는 실제로 필요한 만큼의 I/O임을 고려해야 합니다(앞서의 Merge 조인은 불필요한 전체 데이터를 액세스합니다)

따라서 제 의견은 (Very) Good

 

 

 

 


 

 

 

4. NOT EXISTS + 상관서브쿼리+ TOP 1

2번과 동일합니다. 다만IN이 아니라 EXISTS를 대신 사용했습니다. 여러분은 IN EXISTS중 어는 것을 선호하시나요? 아래 실행 결과를 보시면 2번과 유사하게 Merge Join으로 처리 됩니다. 그래도 전체 데이터를 조인으로 결합시키지 않고, Stream Aggregate 연산자를 이용해서 사실에 결합에 필요한 데이터(89)만 처리하고 있다. 결국 2번보다는 개선된 계획. 그래도 역시 Not bad ^^

 

 

 

 

 

 


 

 

 

5. 상관 서브쿼리+ TOP 1 + IS NULL

드디어 나와 군요. 3번과 함께 제가 가장 좋아하는 데이터 존재 여부 판단용 쿼리 유형입니다. 교과서에도 보기 힘든 쿼리 유형이죠. 실제로 모 고객사에서 쿼리 튜닝을 하면서 고객의 도움으로 우연찮게 발견한 방법입니다. 성능 이득이 너무나 대단해서 그 이후로 저의 필살기가 되었습니다.

^^; 그럼 김정선의 서브쿼리 튜닝 필살기를 여러분께 알려드린 거네요? 후후후, 이미 제가 진행하는 쿼리 튜닝 강의에서 알려 드리고 있습니다. 동일한 내용이므로 역시 (Very) Good!

 

 

 

 


 

 

 

6. OUTER JOIN + IS NULL

이제 나왔네요. OUTER JOIN이 가진 특성을 활용한 방법. 쿼리 자체는 흔하므로 설명 드리지 않아도 될 듯 합니다. 앞의 유형처럼 Merge 조인으로 처리되어 I/O는 작지만, 실행 계획을 보면 문제가 있음을 알 수 있습니다. 내부 입력의 조인 행 수에 대한 문제입니다. Orders 테이블에서 조인 조건을 만족하는 830건을 모두 OUTER 조인으로 결합하고 그 결과 832건을 도출한 뒤에 마지막 Filter 연산자에서 CustomerID IS NULL 조건으로 실제 행 수 2건을 만족하게 됩니다. 반드시 필요한 데이터만 액세스한다는 좋은 쿼리 작성의 기본 원칙에 위배가 되는 것입니다. 따라서 (Too) Bad!

 

 

 

 

 


 

 

 

7. OUTER APPLY + IS NULL

SQL Server 2005에 새로 도입된 OUTER APPLY 문을 적용한 예제입니다. 결과론적으로 앞서 3번 및 5번과 유사한 실행 계획과 I/O를 보여줍니다. 따라서 이 방법 또한 괜찮다는 것을 알 수 있습니다. Good!

 

 

 

 

 


 

 

 

8. EXCEPT + (생략됨) 서브쿼리(혹은JOIN)

수학적인 개념의 차집합(A-B)을 정확히 표현한 것이 바로 SQL Server 2005에 새로 도입된(ANSI 표준이죠 아마?) EXCEPT 문입니다. 아래 실행 계획에서 보듯이 EXCEPT를 사용한 결과는 EXISTS 연산자를 사용한 경우와 동일하게 처리됨을 알 수 있습니다. 그런데 한 가지 문제가 남았습니다. 아래 쿼리와 이전과 다르다는 것입니다. 차집합의 키 원소만을 처리하고 있고, 실제 결과 집합으로 필요한 Customer 테이블의 다른 칼럼 집합은 언급되지 않았다는 것입니다. 코드 주석에 언급했듯이 이 코드에 더해서 다시 조인이나 서브쿼리로 Customers 테이블의 나머지 칼럼을 처리해야 하므로, 결국 부가적인 I/O가 더해질 것입니다. 따라서, 성능은 Not Good!

 

 

 

 

 


 

 

 

SQL Server 2000 vs. 2005, 누가 누가 잘하나?

 

지금까지 살펴본 예제 쿼리들에 대해서 SQL Server 2000과 비교했을 때 2005버전이 크게 달라진 부분이 하나 있습니다. 위 쿼리를 SQL Server 2000(SP3기반)에서 수행 시 가장 큰 차이는 바로 Mere 조인을 사용하지 않는다는 점입니다. Merge조인 예제들이 모두 Nested Loop조인으로 처리됩니다. 그 중 2) NOT IN + 상관서브쿼리 예제를 아래와 같이 비교해 보겠습니다.

 

SQL Server 2000버전) NOT IN + 상관 서브쿼리

Merge 조인을 사용해 I/O를 최소화했던 2005버전과 달리 2000 버전은 Nested Loop 조인을 사용해서 반복 I/O가 검색 행 수만큼 발생했습니다. 사실 상 앞서 우수하다고 판단했던 다른 유형의 쿼리들과 동일하게 처리되고 있습니다. Merge 조인을 위해 불필요한 데이터까지 액세스하지 않고 Index Seek를 통해 필요한 데이터만 제한적으로 검색하고 있습니다. 또한 앞서 언급한Nested Loop 조인의 응답 속도상의 이득도 취할 수 있습니다.

 

 

 

 


 

 

그럼, 이 두 가지를 비교했을 때 과연 어떤 실행 계획이 더 적합한 것일까? 물론 830건 밖에 되지 않는 성능을 논하기엔 매우 작은 테이블과 환경임을 감안하더라도 말입니다. 정답은 없겠지만 적어도 SQL Server 2005의 큰 변화 몇 가지는 확인할 수 있다는 점과 향후 쿼리 튜닝에 있어서 어떤 접근 방법을 우선 시 해야 할지에 대한 중요한 기준을 보여줍니다. 동일한 쿼리에 대해서 2000 2005는 극명한 성능 차이를 보여줄 수 있다는 또 하나의 사례인 셈입니다.

 

철저한 I/O 이득을 우선으로 처리하고 있다는 느낌을 주는 2005 Query Optimizer가 주는 느낌은 왠지 낯설기까지 합니다. 그 변화와 이득은 최대한 활용하되, 파생되는 문제점 또한 해결할 수 있는 다양한 접근 능력이 필요합니다.

 

 

결론

 

최종 판단은 여러분께 맡기겠습니다. 어떤 경우에 어떤 실행 계획이 적합하지 판단하실 수 있다면 그 유형에 맞게 선택해서 사용하시면 됩니다. 더불어 여기에 소개된 것은 기초적인 내용들입니다. 좀 더 복잡한 유형들이 존재합니다. 실제로 여러분들은 어떤 방법, 어떤 유형의 쿼리들을 사용하고 있는지요? 좋은 쿼리가 있으면 소개해 주세요. 많은 분들께 도움이 되실 것이라 믿습니다!

또한 위 쿼리 예제들에 대한 여러분들의 의견도 궁금합니다.

편하게 의견 주세요~~~

 

[MS-SQL] 간단하게 Full Text Search 테스트 하기 Database

2009/03/10 14:36

복사 http://blog.naver.com/ssitech/70043620994

전용뷰어 보기

일단은... 쿼리분석기를 연다. -_- 

 

그리고 아래의 순서대로 진행하면 간단한 테스트를 할 수 있다.

 

1. 기본적으로 FTS(FullTextSaerch)는 비활성화 되어 있으므로 활성화 상태로 바꾼다.

exec sp_fulltext_database @action='enable'

 

2. FTS 카테고리를 하나 생성한다.

 

action 값 에는 당연하겠지만 create , drop 이 있고 더불어 stop , start_full  등이 있다.  상세한건 MSDN 참고 -_-

create , drop 은 생성, 삭제이고 stop 은 잠시 비활성화이며 start_full 은 최초 시작시 카탈로그 내에 인덱스된 내용을 채워주는 역할을 한다. 

 

exec sp_fulltext_catalog @ftcat = 'mail_box', @action = 'create'

 

3. 개별 테이블에 대한 FTS 를 만든다. 아래는  mail_box 테이블에 대한 FTS 를 위에서 생성한 mail_box 카탈로그에 넣어주는 예제이다.  keyname 에는 유니크한 인덱스 명이 들어가면 된다.

 

exec sp_fulltext_table @tabname = 'mail_box', @action = 'create', @ftcat = 'mail_box', @keyname = 'PK_MAIL_BOX'

 

4. FTS 를 적용할 특정 테이블의 컬럼을 지정한다.  action 은 add 와 drop 이 있다. 

exec sp_fulltext_column @tabname = 'mail_box', @colname ='mail_contents', @action ='add'

 

5. FTS 적용한 테이블에 대한 전체 텍스트 인덱스의 전체 태우기를 시작한다.

exec sp_fulltext_table @tabname = 'mail_box', @action = 'start_full'

 

6. 이까지 완료 되었으면 기존 데이타에 대한 FTS 는 처리가 완료되었다.

다음의 형태로 검색을 해보자.

 

SELECT * FROM mail_box WHERE contains(mail_contents,'검색어')

 

증분값에 대한 추가는 아래와 같다.

 

당연히 증분값에 대한 기준점이 필요해진다.  그러기 위해서 timestamp 타입의 컬럼을 추가시킨다.

 

--Timestamp 컬럼을 테이블에 추가.
ALTER TABLE mail_box ADD TStamp timestamp NOT NULL
GO

 

최초의 start_full 명령을 할 시점에 timestamp 속성 컬럼은 존재해야 한다.

 

그 이후에 추가되는 행들에 대한 인덱싱 추가는 아래와 같다.

 

--증분 파퓰레이션 시작
EXEC sp_fulltext_catalog 'mail_box', 'start_incremental'

 

문제는 활용도다.

 

형태소가 아닌 단어중 일부 문자를 입력하는 경우 fulltext 검색의 결과는 like 와 심한 차이를 보인다.

 

-_-

 

이를테면  "서생일" 을 검색할때 like 로는 "%서%"  또는 "%서생%" 등과 같이 일부를 입력한 검색에도 결과물이 잘 나타나지만

 

fulltext 검색의 경우  "서생일"이 아니면 결과물을 못 갖고 오거나 일부만 갖고온다.

 

왜 그럴까나 -_-

 

원래 그렇단다 -_-

 

가 아니고... 이게 형태소 기반의 검색 엔진인 셈인터라 like 로 생각하면 안됨..

 

서생일과 서생 , 생일은 파생어나 유의어 개념이 아닌터라...

 

CONTAINS  로 사용을 하면 색인처리된 like 검색 대용으로 활용 가능할듯..

 


 

 


 이번 장은 C언어의 마지막 장으로 대표적인 함수들과 파일 분할 방법에 데하여 살펴보고 마치도록 하겠습니다.

 [수학 관련 함수]

: 다음과 같은 함수를 사용하기 위해서는 math.h에 선언되어 있으므로 이를 포함해야 합니다.(#include<math.h>)

 double  fabs(double x);  x의 절대값 반환
 double  ceil(double x);  x보다 작지 않은 최소 크기의 정수 반환
 double  floor(double x);  x보다 크지 않은 최대 크기의 정수 반환
 double  exp(double x);  e^x 값 반환
 double  pow(double x, double y);  x^y 값 반환
 double log(double x);  logx값 반환 (밑은 e)
 double log10(double x);  logx값 반환 (밑은 10)
 double sqrt(double x);  루트x 값 반환

 : 다음과 같은 함수를 사용하기 위해서는 stdlib.h에 선언되어 있으므로 이를 포함해야 합니다.(#include<stdlib.h>)

 int  abs(int x);  x의 절대값 반환
 int  labs(long x);  x의 절대값 반환

cf) 실수형 연산을 하는 수학 함수들은 math.h에 선언
     정수형 연산을 하는 수학 함수들은 stdlib.h에 선언

 int rand(void);
->의사 난수를 반환한다. 그러나 rand함수는 난수를 발생시키지만, 그 생성되는 패턴이 항상 동일하기 때문에 진정한 난수는 아니기 때문에 '의사(가짜)' 난수라고 하는 것 입니다.

 rand함수가 동일한 패턴의 난수를 발생시키는 이유는 난수를 생성하는 기초 정보인 시드(seed) 값이 한상 동일하기 때문입니다. 그래서 난수의 생성 패턴을 유동적으로 바꾸기 위해서는 시드값도 바꿔주어야 합니다. 콩심은데 콩나고 팥심은데 팥나죠. 시앗을 바꿔주어야 나오는 결과물도 달라진다고 생각해보세요~

 void srand(unsigned seed);
->함수를 호출하면서 정수를 전달하면, 전달된 정수로 시드 값이 변경됩니다. 때문에 rand함수의 난수 생성 패턴은 달라집니다.

 [시간과 날짜 관련 함수]

시간 관련 함수를 사용하기 위해서는 헤더파일 time.h를 꼭 포함해야 합니다~

clock_t  clock(void);
성공 시 프로세스 타임 반환, 실패 시 형 반환하여 -1 반환
->프로그램이 실행된 이후로 지나간 시간을 의미하는 '프로세스 타임'을 반환합니다. clock_t 형은 좀 더 알아보면 typedef long clock_t로 정의되어 있습니다. 즉, long형으로 새로 정의된 자료형의 이름입니다. 프로스세 타임은 0부터 시작해서 그 값이 증가하는 형태를 띠고 있습니다. 이 값이 1씩 증가하는 시간의 간격(클럭 틱 clock tic)은 매크로 CLOCKS_PER_SEC를 통해서 확인할 수 있습니다. 1초당 클럭 틱이 발생하는 횟수를 의미합니다! 즉 이 값이 1000이라면 클럭 틱은 0.001초에 한번 씩, 1초에 총 1000회의 클럭틱이 발생 했다는 의미입니다.

ex)
   clock_t start, finish;
   start = clock();
      .......
    finish = clock();
    printf(" 소요된 시간 : %f 초", (double) (finish-start)/CLOCKS_PER_SEC);

 time_t  time(time_t*  tptr);
성공 시 1970년 1월 1일 자정 이후로 경과한 시간을 초 단위로 반환, 실패 시 -1
->time 함수는 우리가 일상적으로 사용하는 형태의 날짜와 시간정보를 출력합니다. '1970년 1월 1일 00시 00분 00초' 이후로 경과한 시간을 표현합니다.

ex)
 time_t current;
 current = time(NULL);

 사실 time 함수는 날짜와 시간 정보를 초 단위로 계산하여 (1970년 1월 1일을 기준으로) 반환하기 때문에 현재의 시간과 날짜를 계산하려면 별도의 연산관정을 거쳐야 합니다. 따라서 time 함수가 반환한 값을 가지고 현재의 날짜와 시간을 계산하기 위한 편리한 함수가 ctime 함수입니다.

 char*  ctime(const time_t* tptr);
성공 시 현재 지역의 시간과 날짜를 문자열의 형태로, 실패 시 NULL 반환

ex)
 time_t current;
 current = time(NULL);
 printf("현재 시간 : %s",ctime(&current));

 ctime 함수의 장점은 현재 사긴을 보기 좋게 출력할 수있지만 시간 정보를 가지고 연산하기에는 부족합니다. 이러한 경우 정수의 형태로 년, 월, 일, 시, 분, 초 정보를 추출하기위한 함수가 localtime 입니다.

 struct  tm*  localtime(const time_t* t);
현재 지역의 시간과 날짜 정보를 담은 tm구조체 변수의 포인터 반환

struct tm
{
    int tm_sec;  //0~59
    int tm_min;  //0~59
    int tm_hour;  //0~23
    int tm_mday;  //1~31
    int tm_mon;  //0~11
    int tm_year;  //1900을 기준
    int tm_wday; //요일은 일~토 까지 0 ~ 6으로 표현
    int tm_yday;  //0~365
    int tm_isdst; //써머 타임
 }

위 와 같이 구조체 tm은 정의되어 있다는거 참고해두세요~

ex)
 time_t  current;
 struct  tm*  sptime;

 current = time(NULL);
 sptime = localtime(&current);
 
 printf("년 :  %d \n", sptime->tm_year + 1900);
 printf("월 :  %d \n", sptime->tm_mon + 1);
 printf("일 :  %d \n", sptime->tm_mday);
 printf("시 :  %d \n", sptime->tm_hour);
 printf("분 :  %d \n", sptime->tm_min);
 printf("초 :  %d \n", sptime->tm_sec);

 자 그럼이제 time 함수를 활용하여 난수 생성을 다시한번 시도해봅시다. srand함수의 호출을 통해서 시드 값을 매번 바꿔줘야 한다고 했죠? 역시나 시드 값도 매번 바꿔줘야 한다는 이야기 입니다. 이때!!! time함수를 이용하면 매우 유용합니다.

 srand( (unsigned) time (NULL));
 printf("%d", rand());


 time 함수는 현재의 시간 정보를 반환합니다. 현재 시간이라는 것은 매번 달라지는 값이기 때문에 strand 함수의 전달 인자로 설정해 놓으면, 프로그램이 실행될 때마다 다른 시드 값을 성정하는 효과를 볼 수 있습니다.



 이번에는 파일의 분할에 대하여 알아보도록 하겠습니다. C언어로 구현된 프로그램의 소스코드는 사실 여러 개의 파일로 구성이 됩니다. 몇 천줄, 몇 만줄이나 되는 실제 프로그램의 소스코드는 한 파일에 구성할 수는 없겠죠? 때문에 여러 개의 파일로 소스코드를 나눕니다. 그렇게되면 프로그램의 코드 분석도 용이해지고 관리 또한 쉬워집니다.

 단순히 코드를 나눠버리면 문제가 발생합니다. 컴파일러는 파일 단위로 컴파일을 진행하기 때문에 만약 변수의 선언 부분과 실제 구현 부분이 서로 다른 파일에 존재 한다면 이는 컴파일 오류를 발생시킵니다.

 extern 이라는 키워드는 외부에 선언 및 정의되었다고 컴파일러에게 알려줍니다. 반대로 static 키워드는 외부 파일에서의 접근을 허용하지 않습니다. 중요한건 static은 전역변수와 지역변수의 쓰임새가 조금 다릅니다. 전역 변수로 사용 되었을때 외부 파일에서의 접근을 허용하지 않는다는 의미를 나타냅니다.

 일반적으로 변수의 선언 및 정의 / 함수의 선언 및 정의 / 실제 구현되는 main 코드로 프로그램을 구성하게됩니다. 이들 파일을 생성하고 프로젝트에 추가하는 방법은 글로만 설명하기는 어려우므로 생략하도록 하겠습니다. 아마 C언어 기본서가 있다면 나와있을거라 생각도 되구요. 혹시라도 나중에 기회가 된다면 추가적으로 설명하도록 하겠습니다~ 어찌하다보니까 급 마무리하게 되네요...;;;ㅎㅎㅎㅎㅎ 

 이상으로 C언어에 대한 내용을 모두 마치도록 하겠습니다~ 다음 부터는 C++, My-Sql, 네트워킹등 다양한 주제를 가지고 포스팅을 해 볼 생각입니다~



 

 


 프로그램이라면 기본적으로 갖춰야 할 요소중에 하나가 데이터의 저장입니다. 우리가 일반적으로 접하는 거의 대부분의 프로그램에서는 데이터의 저장이라는 기능이 다양한 형태로 존재하고 있습니다. 때문에 이번 장에서는 파일에 데이터를 저장하고, 저장한 데이터를 참조하는 방법을 알아보도록 하겠습니다.

 우리가 구현한 프로그램과 참조할 데이터가 저장되어 있는 파일 사이에 데이터가 이동할 수 있는 다리를 놓아야 합니다. 컴퓨터 공학에서는 이다리를 '스트림'이라고 하지요

                                             Stream
                 [Program] <-------------------> [Hard Disk]

 파일과의 스트림을 형성하는 방법의 fopen 함수

 FILE*  fopen(const char* filename, const char* mode);
성공 시 해당 파일의 FILE 구조체 포인터, 실패 시 NULL 포인터 반환
-> 스트림을 형성할 때 호출하는 함수입니다.

ex) FILE*  fp = fopen("C:\\prog\\file.txt", "wt");
-> 위 함수의 첫 번째 전달인자는 스트림을 형성할 파일의 경로와 파일의 이름을 알려주고 두 번째 전달인자는 스트림의 종류가 텍스트 데이터를 쓰기 위한 스트림이다라고 알려주는 역할을 합니다. 쓰기모드 즉, 출력스트림이기 때문에 파일에 데이터를 쓸 수 만 있고 읽지는 못합니다. 읽기를 원한다면 "rt"를 사용하면 읽어올 수 있습니다.

 rt : 텍스트 입력용 스트림
 wt : 텍스트 출력용 스트림

 fp라는 파일 구조체 포인터에 스트림을 개방해주었다면 이 포인터 변수를 가지고 활용을 해야겠죠? 실제로 스트림을 형성해서 파일에 데이터를 전송해보고자 한다면 다음과 같은 문장을 사용할 수 있습니다.

 fputc('A', fp);
->fputc 함수를 통해 'A'라는 텍스트를 fp가 가리키는 파일에 저장시킵니다.

cf)참고로 스트림을 형성하는 경우에는 스트림을 형성할 파일이 존재하지 않으면 자동으로 파일이 생성됩니다.

 그렇다면 형성된 스트림의 소멸은 어떻게 해야할까요? fclose 라는 함수가 담당합니다. fopen함수의 반대 기능을 제공합니다.

 int  fclose(FILE* stream);
성공 시 0, 실패시 EOF를 반환
->파일을 닫는다.

 이렇게 fclose 함수의 호출을 통해서 개방되었던 파일을 닫아줘야 하는 이유는 운영체제가  할당한 자원의 반환, 버퍼링 되었던 데이터의 출력에 있습니다. 사용이 끝난 파일은 곧바로 fclose 함수를 호출해는 것이 좋습니다. 사실 파일 스트림을 형성하는 주체는 운영체제입니다. 여기서 운영체제는 스트림의 형성을 위해 시스템의 자원(메모리)을 사용합니다. 때문에 파일을 닫아주지 않으면 할당된 체로 남아있어 자원의 손실로 이어지기때문이죠. 또한 프로그램과 파일의 실제 입출력은 프로그램과 하드디스크 사이의 '버퍼'라는 공간이 존재합니다. 우리가 fputc와 같은 함수의 호출로 데이터를 전송한다고 해서 파일에 바로 저장되는 것이 아니라 일단 버퍼에 저장이 된다음에 운영체제가 정해놓은 버퍼링 방식에 따라 파일이 저장됩니다. fclose 함수의 호출을 통해서 파일을 닫아주면 메모리 버퍼에 저장되어 있던 데이터가 파일로 이동이 되면서 버퍼는 비워지게 됩니다.

 버퍼를 비우고 싶을때 물론 스트림을 종료하지않고말이죠. 그럴때 사용하는 함수가 ffulsh 함수입니다.

 int  fflush(FILE* restrict stream);
성공시 0, 실패 시 EOF 반환
->버퍼를 비워주는 함수

 그러나 fflush함수에서 중요한 것은 입력 스트림을 비우는 요도로 사용할 수 없습니다. 오직 출력 스트림을 비우는 용도로만 사용이 가능하죠^-^

 FILE* fp = fopen("C:\\prog\\test.txt", "rt");
 fflush(fp); //이것은 잘못된 코드

 FILE* fp = fopen("C:\\prog\\test.txt", "wt");
 fflush(fp); //올바른 코드

 출력 버퍼가 비워진다는 것은 출력 버퍼에 저장된 데이터가 느야 소멸되는 것이 아니라, 출력 버퍼에 저장된 데이터가 목적지에 전송이 되어 비워지는 것을 의미합니다.

 이번에는 스트림의 모드에 대하여 살펴보겠습니다. fopen의 두 번째 인자에 전달되는 정보입니다.

 r  :  읽기                                          r+  :  읽기/쓰기
w  :  쓰기                                         w+  :  읽기/쓰기
a  :  파일의 끝에 덧붙여 쓰기               a+  :  읽기/덧붙여 쓰기

 r, r+ 는 파일이 없다면 에러를 발생하지만 나머지는 파일이 없다면 파일을 생성해버립니다. 쉽게 정리하자면 + 는 읽기, 쓰기가 모두 가능한 스트림의 형성을 의미하고 a는 덧붙여 쓰기가 가능한 스트림을 형성합니다.

 근대 우리가 지금까지 사용한 fopen함수를 보면 wt 나 rt를 사용했죠? t 는 무슨 의미일까요? 텍스트 모드라는 뜻 입니다. 바이너리 모드에서는 b를 사용하죠.

  텍스트 모드 : rt, wt, at, r+t, w+t, a+t
  바이너리 모드 : rb, wb, ab, r+b, w+b, a+b

 바이너리 모드에 대해서는 따로 설명하지 않겠습니다. 텍스트모드가 일반적이고 자주사용하니까 굳이 설명안드려도 될 것 같습니다~

 일단 파일 입출력에서 사용하는 함수를 정리해보도록 하겠습니다.

[문자]
 in fgetc(FILE* stream);     //입력
 int getc(FILE* stream);     //입력
 char* fputc(int c, FILE* stream);    //출력
 char* putc(int c, FILE* stream);     //출력

[문자열]
 char* fgets(char* s, int n, FILE* stream);    //입력
 int fputs(const char* s, FILE* stream);     //출력

ex) fgets (buf, 100, fp); //buf는 배열이름, fp는 FILE구조체 포인터
->fp가 가리키는 파일로부터 최대 길이가 100인 문자열을 읽어서 배열 buf에 저장한다.

ex) fputs(buf, fp);
->buf에 저장된 문자열을 fp가 가리키는 파일에 저장한다.

 파일의 끝을 확인 : feof 함수
 int feof(FILE* stream); 
파일의 끝에 도달한 경우 0이 아닌 값 반환
->포인터가 가리키는 파일이 끝에 도달했는지 판단


 서식에 따른 데이터 출력 : fprintf 함수
char name[10] = "boxbop";
char sex = 'M';
int age = 10;
fprintf(fp, "%s %c %d", name, sex, age);    //fp는 FILE 구조체 포인터
->입출력의 대상은 콘솔이 아닌 파일입니다. 이렇게 만들어진 문자열 (boxbop M 10)은 fp가 가리키는 파일에 저장이 됩니다.

 서식에 따른 데이터 입력 : fscanf 함수
char name[10];
char sex;
int age;
fscanf(fp, "%s %c %d", name, &sex, &age);    //fp는 FILE 구조체 포인터
->fp로 부터 파일을 읽어들입니다. 실패하면 EOF를 반환합니다. 기존에 존재하는 파일로부터 데이터를 읽어들이는 겁니다. 사용자로부터 입력받는게 아니에요~ 주의하세요

 이번장은 여기까지 하도록 하겠습니다~ 다음 장이 마지막 장이 되겠네요~
다음 장으로 넘어가도록 하겠습니다^^

+ Recent posts