Search Results for '프로그래밍/윈도우 & MS-SQL'


128 posts related to '프로그래밍/윈도우 & MS-SQL'

  1. 2009/08/16 MSSQL SERVER에서 접속 port 변경하기
  2. 2009/08/16 IIS7 + FastCGI + PHP + MySQL 설치 방법
  3. 2009/08/11 Logparser를 이용한 IIS 로그 Forensic 방법
  4. 2009/08/11 MS SQL 스토어 프로시저 제거
  5. 2009/08/11 MS SQL 2005 xp_cmdshell 오픈하는 방법
  6. 2009/08/11 MS SQL 2000 vs 2005
  7. 2009/08/10 Windows 2008 Server, PHP 5.3, MySQL 5.1 설치기
  8. 2009/08/10 MS-SQL- Login을 각 Database의 User와 동기화하기
  9. 2009/08/10 MS-SQL 모든 테이블의 데이터 일괄 삭제하기
  10. 2009/08/10 [Sequel Safe] SQL 2008 SERVER Login 권한 정책 및 물리 모델 변경 제약
  11. 2009/08/10 SQL 2008 SERVER - hierarchyid의 method 정리
  12. 2009/08/10 SQL 2008 SERVER - SPARSE 컬럼
  13. 2009/08/10 SQL 2008 Server 로그인 및 사용자 권한 정책
  14. 2009/08/10 SQL 2008 온라인 설명서(2009년 5월)
  15. 2009/08/07 25가지 SQL작성법
  16. 2009/08/01 윈도우2003 터미널서버 라이센스 문제
  17. 2009/08/01 "이 제품에 대한 설치 원본을 사용할 수 없습니다." 해결 방법
  18. 2009/08/01 MS-SQL 백업복원후 분리된 사용자 문제 해결
  19. 2009/08/01 MS - SQL에서 도스 명령어를?
  20. 2009/08/01 MS-SQL 약식 테이블 명세서 보기(쿼리문)
  21. 2009/08/01 쿼리분석기, Enterprise Manager등의 툴에서 MSSQL 접속 포트 변경
  22. 2009/08/01 저장프로시저에서 동적 쿼리 사용
  23. 2009/08/01 중복데이터 삭제 쿼리
  24. 2009/07/27 시스템 병목현상 체크 해보기
  25. 2009/07/27 remote.exe 사용법 - Support Kit
  26. 2009/07/27 윈도 2003 필수항목 켜기
  27. 2009/07/27 스트리밍 서버 구축(미디어인코더를 이용한 실시간 스트리밍)
  28. 2009/07/21 windows 터미널라이센스 만료에다른 처리방법
  29. 2009/07/16 mssql 에서의 MD5 이용방법
  30. 2009/05/16 SQL <NULL> 값을 공백값으로 바꾸기(쿼리분석기로)

1. Server(SQL Server 2000 기준)

* 시작 - 모든 프로그램 - Microsoft SQL Server - 서버 네트워크 유틸리티

* 사용할 수 있는 프로토콜에서 TCP/IP를 선택 후 속성

* 원하는 포트 번호로 변경

* SQL Server 재시작


2. Client(ADO를 이용하여 접속할 때)

(서버 주소가 127.0.0.1 이라고 하고, 변경한 포트번호가 3000 일 때)

* "Provider='SQLOLEDB';Data Source='127.0.0.1,3000';Initial Catalog='DB이름';User ID='유저ID';Password='비번';"

* ip 뒤에 포트 번호를 붙일 때 콜론( : ) 이 아닌 콤마( , ) 임에 주목
2009/08/16 18:07 2009/08/16 18:07

IIS7 설치
IIS7 이상 버전을 사용하려면 Vista 또는 Server 2008을 써야 한다. 필자는 Vista만 써봤으므로 그것을 기준으로 하겠다.

제어판 -> 프로그램 -> Windows 기능 추가/제거로 들어가 Windows 기능 창을 연다.
인터넷 정보 서비스 -> 웹 관리 도구를 체크한다. (FTP 등 필요한 것을 더 체크해도 된다.)
확인 눌러서 설치.
웹브라우저에서 http://localhost 또는 http://127.0.0.1을 열고 환영 페이지가 나오는지 확인한다.
기본 웹디렉토리는 C:\inetpub\wwwroot\이므로, UAC 없이 접근하려면 이 폴더의 속성 -> 보안 탭에서 자신의 사용자 계정에 모든 권한을 허가해주면 좀더 편하게 쓸 수 있다.
※ Vista SP1부터는 IIS7 자체에 FastCGI 모듈이 내장되어 있으므로 그것을 쓰면 된다.

PHP 설치
php.net에서 최신 PHP 버전을 받아 설치한다. (5.2 이상 버전 권장, 글 쓰는 현재 5.2.6이 최신 버전임)
이때 installer보다는 zip package를 권장하는데, 그 이유는 isntaller는 설치는 편리하지만 확장 기능(gd, mysql 등등)이 하나도 안 들어있기 때문이다. 나중에 zip package를 받아 확장기능 폴더만 복사해넣어도 되긴 하나 한 번에 하는 게 편하니까 zip package로 바로 하자.

FastCGI를 이용하면 각 연결을 각각의 독립된 프로세스가 처리하게 되므로, 최대한의 성능을 내기 위해 non-thread-safe 패키지를 이용하는 것이 좋다.
적당한 디렉토리에 압축을 푼다.
zip으로 받았을 경우는 그냥 편하게 C:\php에 풀지만, installer로 하면 C:\Program Files\PHP에 설치되므로 참고한다. 여기서는 C:\PHP에 깔았다고 가정하겠다.
IIS 관리자를 열고 왼쪽의 트리에서 사이트 -> Default Web Site를 클릭하면 오른쪽에 관련 작업 아이콘들이 나타난다.
그중 [처리기 매핑]을 더블클릭하고, 오른쪽의 작업 메뉴에서 [모듈 매핑 추가...]를 누른다.
추가 대화상자에서 [요청 경로] : "*.php", [모듈] : "FastCgiModule", [실행 파일 (옵션)] : "C:\PHP\php-cgi.exe", [이름] : "적당히 알아서. 필자는 PHP via FastCGI로 설정했음." 와 같이 설정하고 확인을 누른다.
웹디렉토리(wwwroot)에 info.php를 만들고 "<?php phpinfo(); ?>"라고 써넣은 다음 http://localhost/info.php를 쳐보자.
웹브라우저에 php 정보 화면이 나오면 잘 된 것이다.
Tips!

파일 업로드 기능 사용시 권한 관련 문제를 해결하려면 php.ini에서 uploaded_tmp_dir을 기본값이 아닌 다른 것으로 바꿔주는 것이 좋다. (IIS_IUSRS가 모든 권한을 가지는 디렉토리로)
php.ini의 설정을 변경하고 이것을 적용하려면, 웹사이트가 아닌 그 웹사이트에 연결된 응용프로그램 풀을 재생(refresh)해주면 된다. ISAPI 핸들러 형태로 php를 사용할 경우는 웹서버를 재시작하면 되지만, FastCGI의 경우 php가 외부 프로세스 형태로 실행되므로(IIS7의 기본 설정을 이용할 경우 NETWORK SERIVCE 사용자 권한을 가진다) 이를 관리해주는 응용프로그램 풀을 다시 로드해야 한다.
FastCGI를 위한 php.ini 추가 설정 참고:
fastcgi.impersonate = 1
cgi.fix_pathinfo = 1
cgi.force_redirect = 0
extension_dir = "./ext"
MySQL 설치
mysql.com에서 적당한 버전을 받아 설치한다. 64bit 운영체제를 사용하더라도, php의 64bit용 Windows binary가 제공되지 않으므로 32bit를 쓰는 것이 편하다.
패키지 중에 Windows Essentials를 받으면 무리 없다.
(64bit와도 연동은 가능하지만 설정 과정에서 약간의 귀찮음이 있다.)
설치 완료 후 MySQL Server Instance Config Wizard를 실행한다.
설정 과정에서 root 암호 및 기본 인코딩(기본 인코딩은 UTF-8 권장) 등을 지정하고, 커맨드 프롬프트에서 바로 실행할 수 있도록 PATH 추가 옵션을 체크해준다.
PHP에서 인식시키기 위해, C:\PHP\php.ini에서 주석처리되어 있는 extension=php_mysql.dll을 주석 해제한다. (줄 앞에 붙은 세미콜론을 지워준다)
내용이 없으면 적당한 곳에 추가해주면 된다. 취향에 따라 gd, mysqli, curl 등등을 켜준다.
MySQL 설치된 폴더 안의 bin 폴더에 들어있는 libMYSQL.dll을 C:\Windows\System32 (32bit 윈도의 경우) / C:\Windows\SysWOW64 (64bit 윈도의 경우)에 복사한다.
다시 http://localhost/info.php를 열고 mysql 모듈이 잘 올라왔는지 확인한다. 만약 안 보일 경우 IIS 관리자에서 사이트를 재시작해준다.
커맨드 프롬프트에서 mysql -uroot -p를 실행하여 사용자 계정 등을 설정한다. 자세한 건 검색. -_-
간단한 php 스크립트를 만들어 접속 여부를 테스트해본다.

2009/08/16 18:06 2009/08/16 18:06
Logparser는 MS에서 만든 강력한 IIS, W3C, 이벤트 로그 분석툴로서 SQL 쿼리타입으로 조건별 검색할 수 있는 강력한 툴입니다.

1) 가장 최근에 생성된 시간을 기준으로 ASP 스크립트를 변조한 Trojan Files 여부를 진단
 
C:\logparser2.2\logparser -i:FS "SELECT TOP 20 Path, CreationTime FROM C:\inetpub\wwwroot\*.* ORDER BY CreationTime DESC" -rtp:-1 


2). 가장 최근에 수정된 Files 로그 찾기

C:\logparser2.2\logparser -i:FS "SELECT TOP 20 Path, LastWriteTime FROM C:\inetpub\wwwroot\*.* ORDER BY LastWriteTime DESC" -rtp:-1   
  
3). 해커가 Trojan Files을 삭제한 경우에 HTTP 200 서버코드 흔적 로그를 찾는다.
 
C:\logparser "SELECT DISTINCT TO_LOWERCASE(cs-uri-stem) AS URL, Count(*) AS Hits FROM ex*.log WHERE sc-status=200 GROUP BY URL ORDER BY URL"    -rtp:-1  
 
* nc.exe, tini.exe, root.exe, cmd.exe, upload.asp, aspexec.asp, cmd.asp 같은 파일 이름이 있으면 의심

4) Script Abuse 분석(가장 많은 Request 요청을 받은 Executable 파일의 확장자 확인)

C:\logparser -i:FS "SELECT TO_LOWERCASE(SUBSTR(Name, LAST_INDEX_OF(Name, '.'),  STRLEN(Name))) AS Extenstion, Count(*) AS Files FROM C:\inetpub \wwwroot\*.*, C:\inetpub\scripts\*.* WHERE Attribute NOT LIKE 'D%' GROUP BY Extenstion ORDER BY Files DESC" -rtp:-1 

* 특히, .ASP, .DLL 파일 요청을 유심히 봐야함

5) HTTP 서버 500 에러코드 검사

C:\logparser "SELECT [cs-uri-stem], [cs-uri-query], Count(*) AS [Hits] FROM c:\logs\web\ex*.log WHERE sc-status = 500 GROUP BY [cs-uri-stem], [cs-uri-query] ORDER BY [hits], [cs-uri-stem] DESC" -rtp:-1 -i:iisw3c
 

6) 가장 많은 Request Hit 수를 높음 ASP, DLL 파일 확인

C:\logparser "SELECT TO_STRING(TO_TIMESTAMP(date, time), 'yyyy-MM-dd') AS Day, cs-uri-stem, Count(*) AS Total ex*.log WHERE (sc-status<400 or sc-status>=500) AND (TO_LOWERCASE(cs-uri-stem) LIKE '%.asp%' OR TO_LOWERCASE(cs-uri-stem) LIKE '%.exe') GROUP BY Day, cs-uri-stem ORDER BY cs-uri-stem, Day" -rtp:-1 

7) 시간당 에러수가 가장 많이 발생한 날짜 확인
 
C:\logparser "SELECT date, QUANTIZE(time, 3600) AS hour, sc-status, Count(*) AS Errors FROM ex03*.log WHERE sc-status>=400 GROUP BY date, hour, sc-status HAVING Errors>25 ORDER BY Error DESC" -rtp:-1 

* 25개 이상의 에러코드(404코드)를 발생한 날짜와 시간 결과를 출력

8) 하루동안 50번이상 동일 페이지에 접속을 시도한 클라이언트 IP 확인
 
C:\logparser "SELECT DISTINCT date, cs-uri-stem, c-ip, Count(*) AS Hits FROM ex*.log GROUP BY date, c-ip, cs-uri-stem HAVING Hits>50 ORDER BY Hits DESC" -rtp:-1 

9) 하루동안 50번이상 동일 페이지에 접속을 시도한 클라이언트 IP 확인
 
C:\logparser "SELECT DISTINCT date, cs-uri-stem, c-ip, Count(*) AS Hits FROM ex*.log GROUP BY date, c-ip, cs-uri-stem HAVING Hits>50 ORDER BY Hits DESC" -rtp:-1 

10)  모든 ASP 에러 기록 확인
 
C:\logparser "SELECT cs-uri-query, Count(*) AS Total FROM ex*.log WHERE sc-status>=500 GROUP BY cs-uri-query ORDER BY Total DESC" -rtp:-1 

* 특히, ODBC와 ADO 에러는 SQL Injection 가능성이 있으므로 주의깊게 살펴봐야 함

11) 스크립트 및 Executable 파일의 HTTP 서버 코드 기록 확인
 
C:\logparser "SELECT cs-uri-stem, sc-status, Count(*) AS Total FROM ex*.log WHERE TO_LOWERCASE(cs-uri-stem) LIKE '%.asp%' or TO_LOWERCASE(cs-uri-stem) LIKE '%.exe%' GROUP BY cs-uri-stem, sc-status ORDER BY cs-uri-stem, sc-status" -rtp:-1 

12) Win32 Status Code 분석을 통한 Attack 확인
 
C:\logparser "SELECT cs-uri-stem, WIN32_ERROR_DESCRIPTION(sc-win32-status) AS Error, Count(*) AS Total FROM ex*.log WHERE sc-win32-status>0 AND (TO_LOWERCASE(cs-uri-stem) LIKE '%.asp%' OR TO_LOWERCASE(cs-uri-stem) LIKE '%.exe%') GROUP BY cs-uri-stem, Error ORDER BY cs-uri-stem, Error" -rtp:-1
 

13) HTTP Method 통계 분석
 
C:\logparser "SELECT cs-uri-stem, cs-method, Count(*) AS Total FROM ex*.log WHERE (sc-status<400 or sc-status>=500) AND (TO_LOWERCASE(cs-uri-stem) LIKE '%.asp%' or TO_LOWERCASE(cs-uri-stem) LIKE '%.exe%') GROUP BY cs-uri-stem, cs-method ORDER BY cs-uri-stem, cs-method" -rtp:-1
2009/08/11 14:50 2009/08/11 14:50
아래 리스트에 있는 확장 프로시저는 가급적이면 모두 제거해 주는 것이 좋습니다.
 
use master
exec sp_dropextendedproc 'xp_cmdshell'
exec sp_dropextendedproc 'xp_dirtree'
exec sp_dropextendedproc 'xp_enumgroups'
exec sp_dropextendedproc 'xp_fixeddrives'
exec sp_dropextendedproc 'xp_loginconfig'
exec sp_dropextendedproc 'xp_enumerrorlogs'
exec sp_dropextendedproc 'xp_getfiledetails'
exec sp_dropextendedproc 'Sp_OACreate'
exec sp_dropextendedproc 'Sp_OADestroy'
exec sp_dropextendedproc 'Sp_OAGetErrorInfo'
exec sp_dropextendedproc 'Sp_OAGetProperty'
exec sp_dropextendedproc 'Sp_OAMethod'
exec sp_dropextendedproc 'Sp_OASetProperty'
exec sp_dropextendedproc 'Sp_OAStop'
exec sp_dropextendedproc 'Xp_regaddmultistring'
exec sp_dropextendedproc 'Xp_regdeletekey'
exec sp_dropextendedproc 'Xp_regdeletevalue'
exec sp_dropextendedproc 'Xp_regenumvalues'
exec sp_dropextendedproc 'Xp_regread'
exec sp_dropextendedproc 'Xp_regremovemultistring'
exec sp_dropextendedproc 'Xp_regwrite'
drop procedure sp_makewebtask
go
2009/08/11 14:49 2009/08/11 14:49

MS SQL 2005 부터는 xp_cmdshell를 오픈할 수 있는 방법이 변경되었습니다.

1. SQL2005 하에서 'xp_cmdshell' Open하는 방법 :
 

> sp_configure 'show advanced options', 1;
go
RECONFIGURE;
go

> sp_configure 'xp_cmdshell', 1;
go
RECONFIGURE;
go


2. SQL2005 에서 'OPENROWSET' 오픈하는 방법:

> sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO

> sp_configure 'Ad Hoc Distributed Queries', 1;
GO
RECONFIGURE;
GO

2009/08/11 14:04 2009/08/11 14:04

MS SQL 2005 서버가 점점 많아지면서 진단시 기존의 2000과 쿼리명에 약간의 변경이 있습니다.

1. 테이블의 모든 계산 열(Computed Column) 찾기

1) SQL SERVER 2000
select name from syscolumns where id =object_id('TableName') and iscomputed=1


2) SQL SERVER 2005
select name from sys.computed_columns where object_id =object_id('TableName')

[참고]

SQL Server 2005에서는 계산된 열을 지속형(Persisited)으로 설정할 수 있습니다. 따라서, 지속형(Persisted)으로 설정되지 않은 계산된 열을 확인하기 위해서 다음과 같이 조건을 추가할 수 있습니다.:

select * from sys.computed_columns where is_persisted=0

2. ID열이 있는 테이블 목록 조사하기

1) SQL SERVER 2000
select object_name(id),name from syscolumns where columnproperty(id,name,'IsIdentity')=1

2) SQL SERVER 2005
select object_name(object_id),name from sys.identity_columns

[참고]
SQL Server 2005 에서는 id열의 가장 마지막 값을 별도로 저장합니다. 다음과 같은 쿼리를 이용해서 이를 확인할 수 있습니다..

select name,last_value from sys.identity_columns

3. 현재 Instance의 모든 데이터베이스 알아내기

1) SQL SERVER 2000
select name from master..sysdatabases

2) SQL SERVER 2005
select name from sys.databases

4. 데이터베이스의 모든 저장 프로시저 리스트 알아내기

1) SQL SERVER 2000
select name from sysobjects where type='P'

2) SQL SERVER 2005
select name from sys.procedures

[참고]
다음과 같은 조건으로 저장 프로시저가 복제에서 이용되는지 여부와 SQL Server가 시작할 때 자동으로 시작하는지의 여부를 확인할 수 있습니다.
select name from sys.procedures where is_execution_replicated=1
select name from sys.procedures where is_auto_executed=0

5. 데이터베이스의 모든 테이블 리스트 알아내기

1) SQL SERVER 2000
select name from sysobjects where type='U'

2) SQL SERVER 2005
select name from sys.tables

[참고] : 다음과 같은 조건으로 복제되는 테이블의 리스트를 확인할 수 있습니다.
select * from sys.tables  where is_replicated =1

6. 데이터베이스의 모든 뷰 리스트 알아내기

1) SQL SERVER 2000
select name from sysobjects where type='V'

2) SQL SERVER 2005
select name from sys.views

7. 데이터베이스의 모든 트리거 리스트 알아내기

1) SQL SERVER 2000
select name from sysobjects where type='TR'

2) SQL SERVER 2005
select name from sys.triggers where parent_class=1

[참고]
다음과 같은 조건으로 어셈블리(CLR) 트리거와 SQL 트리거를 구분할 수 있습니다. (TA : 어셈블리 트리거, TR : SQL 트리거) 또한 After 트리거인지 Instead Of 트리거인지도 구분 가능합니다.
select name from sys.triggers where type='TA'
select name from sys.triggers where type='TR'
select name from sys.triggers where is_instead_of_trigger=1

8. 서버의 모든 로그인 리스트 알아내기

1) SQL SERVER 2000
select * from master..syslogins where isntgroup=0 and isntname=0

2) SQL SERVER 2005
select * from sys.sql_logins

9. 데이터베이스의 모든 SQL 개체에 대한 종속성 확인하기

1) SQL SERVER 2000
select * from sysdepends

2) SQL SERVER 2005
select * from sys.sql_dependencies

10. SQL Server의 모든 데이터 유형 확인하기

1) SQL SERVER 2000
select * from systypes

2) SQL SERVER 2005
select * from sys.systypes

11. SQL Server의 모든 에러 메시지 확인하기

1) SQL SERVER 2000
select * from master..sysmessages

2) SQL SERVER 2005
select * from sys.messages

12. 현재 데이터베이스의 데이터 파일 확인하기

1) SQL SERVER 2000
select name,filename from sysfiles

2) SQL SERVER 2005
select name, physical_name from sys.database_files

13. 현재 데이터베이스의 모든 인덱스의 유형 확인하기

1) SQL SERVER 2000
sysindexes 테이블의 indid 열을 이용해서 구분

2) SQL SERVER 2005
select object_name(object_id),name, type_desc  from sys.indexes where type_desc ='CLUSTERED'
select object_name(object_id),name, type_desc  from sys.indexes where type_desc ='HEAP'
select object_name(object_id),name, type_desc  from sys.indexes where type_desc ='NONCLUSTERED'
select object_name(object_id),name, type_desc  from sys.indexes where type_desc ='XML'

2009/08/11 14:00 2009/08/11 14:00
흠.. 닷넷 만지다가 도피를 위해 PHP와 MySQL을 깔았는데..
요즘 세상 참 좋아졌다는 생각이 들었습니다.
PHP와 MySQL이 마법사식으로 까는건 뭐 일도 아닌데.
이제는 윈도우에 대한 배려(?)도 해주는듯 손쉽게 PHP+MySQL을 깔아줍니다.

그 과정을 여러분께 소개하려고 합니다.
먼저, Windows 2008에 IIS를 깔았습니다. 윈도우 서버를 사용하면 IIS를 쓰지 아파치 쓰는건 이건 좀 사치가 아닌가요?ㅋㅋ
어쨌든 간에 IIS를 깔고, 그리고 필수적으로 깔아야 하는게 CGI입니다.

전에 윈도우 2008 사이트에서 아주 놀고있는 광고를 했습니다.
PHP 사이트에도 강력하다고 홍보하는 윈도우 2008 광고를 보면서.
닷넷은 뒀다 모할거냐는 의문점이 들기도 했습니다........
이거 원..

어쨌든 IIS와 CGI를 깔았으면 그다음 필수적으로 깔아줘야 하는게 있습니다.

MS에서 제공하는 Web Platform Installer입니다.

유의하실 점은 업데이트 도중에 이 프로그램으로 설치하면 설치 안되는 일이 발생할 수 있습니다. 업데이트 싹 하거나 업데이트를 아예 멈추고 하시기 바랍니다.
저같은 업뎃때문에 설치 실패하는 일이 있었습니다.
어쨌든, 설치합시다.
http://www.microsoft.com/web/downloads/platform.aspx

윈도우 XP 이상이면 깔 수 있으며, 윈도우 XP Pro에 딸린 10명짜리 IIS 5.1도 구축이 가능합니다. 동시접속자수 10명 제한 낄낄. 무슨 이거..
윈도우 비스타에 홈서버 버전도 있는데 그거 아시는분 알려주셈,.
(근데 왜 MS에서는 유독 한국에만 홈서버나 서버 OS중 웹서버 기반 에디션을 출시 안하는건지 원..)

다운받고 실행하면 자동적으로 컴퓨터에 나도 모르게 깔리며(...) 설치할 목록들이 아주 쫘악 나옵니다.

여기서 주목할 것은, 워드프레스도 있습니다. 낄낄.

Visual Web Developer로도 충분히 닷넷 웹사이트도 만들고 웹사이트 만들 수 있는 강력한 IDE에다 무료이긴 한데.. 음.. 그건 선택사항이니 쓰실분은 쓰셈.

여기에 보시면 PHP 5.2.10이 있습니다. 설치를 해도 되지만, 5.3을 쓸려면 굳이 체크는 안해도 됩니다.

그리고 IIS 6.0이거나 7.0이면 FastCGI가 보입니다. 꼭 설치하는게 좋습니다.

그리고 IIS7.0 이상일 경우 URL Rewrite가 있습니다. 2.0 베타버전도 보이는데 안써봐서 모르겠고, 1.0 깔아도 됩니다. 심심하면 2.0 깔아보는것도 좋을듯.

어쨌든 설치할 건 뭐 별로 없는 편입니다. 설치하면 다운 "받으면서 설치"합니다.
참 기이한 설치 화면이죠.

이렇게 해서 컹그레츄에이션이라고 뜨면 닫습니다.

자, 이제 PHP와 MySQL을 깔아봅시다.

아참, Zend Platform이 있습니다. PHP와 MySQL을 한번에 설치해주고 최적화까지 해버린 강력한 플랫폼입니다. 무료 버전도 정말 좋긴 한데..
제가 예전에 2008에서 깔았는데 갑자기 서버가 바보가 되버려서 지웠습니다.
근데 저처럼 서버가 바보 안되고 멀쩡하면 그거 쓰는것도 좋을 듯 하군요.

PHP 5.3은 여기서 받고,
http://windows.php.net/download/

MySQL 5.1은 여기서 받습니다.
http://dev.mysql.com/downloads/

그리고 이 환경에 PHPMyAdmin도 빼놓을 수 없죠.
http://www.phpmyadmin.net

자. PHP와 MySQL은 마법사가 뜹니다.
이때, PHP는 IIS FastCGI로 설정하면 지가 알아서 FastCGI와 처리기 매핑에 등록됩니다.
그리고 MySQL은 설치가 끝나면 마법사가 뜨는데, 그다지 만질 건 없습니다.

그냥 다음-> 다음 -> 다음.... 일반으로 사용한다면 그냥 기본값으로 써도 무리없습니다.
그리고 MySQL을 윈도우 서비스에 등록되 실행됩니다.
이때, 처음으로 마법사가 뜨기 때문에 root의 암호를 지정할 수 있습니다.
이럴때 암호를 지정하면 좋겠죠. 그리고 한국어기 때문에 언어 선택시
日本語라고 말풍선으로 재잘되는놈으로 선택하면 기본 언어셋이 유니코드가 됩니다.
아니면 그냥 순수 한국어가 좋다면 한국어 언어셋으로 직접 타이핑으로 등록해도 됩니다.

주저리주저리 설정하면 어느세 PHP와 MySQL 환경 구축은 끝.

자, 이제 사이트를 하나 만들어 만들어봅시다.

시작 -> 실행 -> inetmgr 엔터.

역시 그냥 콘솔식이 빠릅니다.ㅋㅋㅋㅋㅋㅋ
이렇게 IIS 관리에 들어갑니다. 서버를 선택한 다음 사이트로 가서 새 사이트 추가합니다.
IIS 6.0에 비해 IIS 7.0부터는 마법사 형태가 아닌 원샷 형태입니다. 좋아요.ㅋㅋ
그리고 응용 어플은 기본적으로 지가 알아서 새로 만듭니다.
근데 왠만하면 응용 어플을 하나 만들고 하는게 성능 면에서 좋습니다.
응용 풀 추가 -> 이름은 아무거나, 닷넷프레임워크 버전은 관리코드없음, 관리모드는 통합. 확인. 끝.
그런 다음에 이 응용 풀에 PHP 사이트를 만들면 닷넷이 관여하지 않기 때문에 바로 슝 왔다갔다할수 있고, 관리 기능 목록이 간결해집니다.

어쨌든 응용풀 만들고 사이트를 만들었으면, 기본적으로 html,htm은 PHP가 관여하지 않습니다. 만약에 원하면 html과 htm 등을 PHP 스크립트가 돌아가게 할 수 있습니다.
먼저 만든 사이트를 클릭하면 기능 목록이 뜹니다. 처리기 매핑을 누릅니다.
거기서 작업탭에 모듈 매핑을 추가합니다.
요청 경로에 확장자를 입력합니다. *.htm 이런식으로. 복수 확장자는 불가능하니 항상 단 하나의 확장자만 입력하세요. 단점이긴 하지만 어쩔수가 없습니다.
모듈은 FastCgiModule을 선택합니다.
실행 파일은 PHP 실행 파일을 선택합니다. PHP는 기본적으로 깔린 폴더가
C:\Program Files\PHP\php-cgi.exe입니다.
이때, 그냥 쓰고 확인누르면 오류납니다. 따옴표 적으라는 소리죠. 따옴표로 감싸주시고,
요청 제한에서 매핑 탭에 요청이 어쩌구에 체크표시합니다. 그런 다음 파일 또는 폴더로 해주면 나중에 리라이트할때 집나가면 개고생이다 소리 안할 수 있습니다.
이렇게 해서 PHP 사이트 구축은 끝났습니다.
이제 PHP가 돌아가는지 테스트해봅시다.
index.php을 만들고 phpinfo()를 작성합니다.

자 이제 띄워보면 절대 멀쩡하게 뜰리가 없고 에러가 발생합니다.
기본적으로 윈도우2008에 제공되는 IE에서는 PHP 에러메시지조차 안뜨고 페이지를 표시할 수 없다고 뜹니다. 그 문제는 인터넷 옵션에 HTTP 오류 보기를 체크해제하면 해결.
그러면 이제 PHP 오류를 볼 수 있습니다.
아시겠지만 PHP 5대부터는 short_tag가 off 되있습니다. 하지만 웹플랫폼 인스톨러를 통해 깐 PHP는 왠만한 편리한 PHP 설정으로 되있어서 바로 써먹을 수 있습니다. 미리 설정을 하고 깔아주기 때문에 편리함은 그게 더하지만.
어쨌든, 하실분은 하시고 안하실라면 하지 마시고, 그러면 이번엔 길~다란 에러가 뜹니다.
PHP 5.3대 설치시 뜨는 이렇게 기다란 에러는 Timezone을 설정하지 않아서입니다.
귀찮게 하죠 참..
php.ini에서 [date] 검색한다음 그아래 timezone에 주석을 풀고 Asia/Seoul을 입력합니다.

자 이제 실행하면 이제 아주아주아주 잘뜨는 감격스런 phpinfo가 뜹니다.

PHPmyadmin은 새 가상 디렉터리로 잡거나 아니면 IIS7의 경우 새 응용프로그램 풀이 있습니다. 그걸로 하셔도 됩니다. 둘이 뭐 다를 건 없죠. 단지 사이트의 하위 응용 프로그램은 부모에 상속은 되지만, 가상 디렉터리에 비해 부모 설정을 거기서 또 할수 있는 매력이 있습니다.
예를들어 닷넷없는 사이트 하위 디렉터리에 닷넷전용 디렉터리 만들 용도다 할때 쓰면 좋겠죠.
어쨌든 주저리주저리하지만 그다지 어렵지는 않습니다.

몇가지 덧붙이자면, PHP5.3 설치할때 full로 까시거나 custom할때 mbstring은 꼭 깔아야 나중에 한글 가지고 놀때 부담이 줄어들겠죠.
그리고 phpmyadmin에서 mcrypt 때문에 메시지 뜨면
http://files.edin.dk/php/win32/mcrypt/
에서 libmcrypt.dll을 받아서 system32 폴더와 php 폴더에 넣고 서버를 재시작하면 됩니다.
이래도 적용이 안된다면 전과 같은 방법으로 mcrypt를 넣고 다시 PHP를 설치하면 됩니다.

윈도우 2008과 PHP. 쓸만합니다. 리라이트가 있어서 빛이 더해지는군요.
리라이트 모듈은.. 음.. 쩝;; 그냥 아파치 리라이트 만든 다음에 URL Rewrite 기능에 들거가Import Rules 클릭한 다음 스크립트를 넣거나 .htaccess 파일을 첨부하면 지가 알아서 해석해서 넣어줍니다. Filesmatch와 헤더를 넣으신 분은 처리기 매핑을 이용하실수밖에.
IIS 에서는 지원 안합니다.
2009/08/10 12:31 2009/08/10 12:31
백업 파일로부터 DB를 새로 복원할 때 곤란한 점은 일일이 DB의 User와 SQL서버의 Login을 매핑해 줘야 한다는 점이다.

아래 스크립트를 사용하면 이 작업을 한번에 처리할 수 있다.


1. User와 Login의 Sync가 맞지 않는 내역이 있는지 확인

DECLARE @nvcCollation sysname;

DECLARE @nvcStmt nvarchar(4000);

DECLARE @tblTemp table (

       DBName sysname NOT NULL,

       UserName sysname NOT NULL,

       LoginName sysname NOT NULL

);

 

SET @nvcCollation = CAST(DatabasePropertyEx('master', 'Collation') AS sysname);

SET @nvcStmt = N'

USE [?];

SELECT ''?'', A.name, B.loginname

FROM sys.sysusers A

       INNER JOIN master.dbo.syslogins B ON A.name COLLATE ' + @nvcCollation + N' = B.Name

       INNER JOIN master.dbo.sysdatabases C ON C.name = ''?''

WHERE A.issqluser = 1 AND (A.sid IS NOT NULL AND A.sid <> 0x0)

       AND SUSER_SNAME(A.sid) IS NULL

       AND (C.status & 32) =0 --loading

       AND (C.status & 64) =0 --pre recovery

       AND (C.status & 128) =0 --recovering

       AND (C.status & 256) =0 --not recovered

       AND (C.status & 512) =0 --offline

       AND (C.status & 1024) =0 --read only

ORDER BY A.name';

 

INSERT @tblTemp EXEC sp_msforeachdb @nvcStmt;

 

SELECT * FROM @tblTemp;

 


2. 위 스크립트에서 레코드가 반환된다면 => User와 Login을 Sync해 주기

DECLARE @nvcCollation sysname;

DECLARE @nvcStmt nvarchar(4000);

 

SET @nvcCollation = CAST(DatabasePropertyEx('master', 'Collation') AS sysname);

SET @nvcStmt = N'

USE [?];

DECLARE @nvcUserName sysname;

DECLARE @nvcLoginName sysname;

 

DECLARE SyncDBLogins CURSOR FOR

       SELECT A.name AS userName, B.loginname AS loginName

       FROM sys.sysusers A

             INNER JOIN master.dbo.syslogins B ON A.name COLLATE ' + @nvcCollation + N' = B.Name

             INNER JOIN master.dbo.sysdatabases C ON C.Name = ''?''

       WHERE A.issqluser = 1

             AND (A.sid IS NOT NULL AND A.sid <> 0x0)

             AND suser_sname(A.sid) IS NULL

             AND (C.status & 32) =0 --Loading

             AND (C.status & 64) =0 --pre recovery

             AND (C.status & 128) =0 --recovering

             AND (C.status & 256) =0 --not recovered

             AND (C.status & 512) =0 --offline

             AND (C.status & 1024) =0 --read only

       ORDER BY A.name;

 

OPEN SyncDBLogins;

 

FETCH NEXT FROM SyncDBLogins INTO @nvcUserName, @nvcLoginName;

 

WHILE @@FETCH_STATUS = 0

BEGIN

       EXEC sp_change_users_login ''update_one'', @nvcUserName, @nvcLoginName;

    FETCH NEXT FROM SyncDBLogins INTO @nvcUserName, @nvcLoginName;

END;

 

CLOSE SyncDBLogins;

 

DEALLOCATE SyncDBLogins;'

 

EXEC sp_msforeachdb @nvcStmt;




출처 : http://www.sqlservercentral.com/articles/Log+Shipping/63028/
2009/08/10 12:18 2009/08/10 12:18

프로젝트 초기에 개발 DB에서 자주 사용할 만한 쿼리일 듯 ^^

 

EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'

EXEC sp_MSForEachTable 'ALTER TABLE ? DISABLE TRIGGER ALL'

EXEC sp_MSForEachTable 'DELETE FROM ?'

EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'

EXEC sp_MSForEachTable 'ALTER TABLE ? ENABLE TRIGGER ALL'

 

출처 : http://www.devx.com/dbzone/Article/40967

 

하지만, 그대로 사용하기엔 좀 부족해 보인다.

아래 사항을 추가해서 사용해야겠다.

1.     삭제하지 않을 테이블을 지정할 수 있을 것.

2.     DELETE문 대신 TRUNCATE TABLE문을 사용할 수 있다면… TRUNCATE TABLE문을 쓰도록 분기할 것. (테이블이 VIEWschema binding되어 있다면… DELETE문을 쓸 수 없을 듯)

3.     IDENTITY 속성의 컬럼을 포함한 경우, Reseed 할 것.
이때, 한번도 데이터가 INSERT되지 않았거나 TRUNCATE한 테이블과그렇지 않은 테이블의 Reseed 값을 달리 적용해야 함에 유의!!!



위의 조건 중 1번, 3번 항을 적용한 스크립트. ^^


소스 코드는 아래와 같습니다.

-- SQL Server 2005 이상에서사용할수있습니다.

-- DELETE문을사용하므로대용량테이블이존재한다면이스크립트는부적합할수있습니다.

-- Ctrl-Shift-M을눌러데이터베이스이름과삭제하지않을테이블을설정한후실행합니다.

 

USE <Database Name,sysname,>;

GO

 

SET NOCOUNT ON;

GO

 

DECLARE

    @nvcStmt nvarchar(max),

    @nvcIgnoreTables nvarchar(max);

 

DECLARE @tblTargetTables table (

    [object_id] int NOT NULL PRIMARY KEY,

    schemaName sysname NOT NULL,

    tableName sysname NOT NULL

);

 

DECLARE @tblIdentityTables table (

    tableName sysname NOT NULL,

    seed_value int NOT NULL,

    increment_value int NOT NULL,

    last_value int NULL

);

 

SET @nvcIgnoreTables = N'<삭제제외테이블을comma를구분자로나열,,>';

 

-- 삭제대상테이블정보를수집합니다.

INSERT @tblTargetTables ([object_id], schemaName, tableName)

SELECT T.[object_id], S.name, T.name

FROM sys.tables T

    INNER JOIN sys.schemas S ON T.[schema_id] = S.[schema_id]

WHERE T.type = 'U' AND NOT EXISTS (

    SELECT *

    FROM (

        SELECT LTRIM(RTRIM(SUBSTRING(

              N',' + @nvcIgnoreTables + N','

            , number + 1

            , CHARINDEX(N',', N',' + @nvcIgnoreTables + N',', number + 1) - number - 1

        ))) AS tableName

        FROM master.dbo.spt_values

        WHERE [type] = 'P' AND number < (DATALENGTH(N',' + @nvcIgnoreTables + N',') / 2)

            AND SUBSTRING(N',' + @nvcIgnoreTables + N',', number, 1) = N','

    ) S

    WHERE tableName = T.name

);

 

-- 삭제대상테이블의identity 속성컬럼정보를수집합니다.

INSERT @tblIdentityTables (tableName, seed_value, increment_value, last_value)

SELECT T.tableName, CAST(I.seed_value AS int), CAST(I.increment_value AS int)

    , CAST(I.last_value AS int)

FROM @tblTargetTables T

    INNER JOIN sys.identity_columns I ON T.[object_id] = I.[object_id];

 

-- CONSTRAINTTRIGGER를비활성화하는구문생성

SET @nvcStmt = N'DISABLE TRIGGER ALL ON DATABASE;

EXEC sp_MSForEachTable ''ALTER TABLE ? NOCHECK CONSTRAINT ALL'';

EXEC sp_MSForEachTable ''ALTER TABLE ? DISABLE TRIGGER ALL'';';

 

-- 테이블DELETE 구문생성

SELECT @nvcStmt = @nvcStmt + NCHAR(13) + NCHAR(10) +

    N'DELETE ' + QUOTENAME(schemaName) + N'.' + QUOTENAME(tableName) + N';'

FROM @tblTargetTables;

 

-- identity 속성의컬럼을초기화하는구문생성

SELECT @nvcStmt = @nvcStmt + NCHAR(13) + NCHAR(10) +

    N'DBCC CHECKIDENT(''' + tableName + ''', RESEED, ' +

    CASE

        WHEN last_value IS NULL THEN CAST(seed_value AS nvarchar(10))

        ELSE CAST(seed_value - increment_value AS nvarchar(10))

    END + N');'

FROM @tblIdentityTables;

 

SET @nvcStmt = @nvcStmt + '

EXEC sp_MSForEachTable ''ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL'';

EXEC sp_MSForEachTable ''ALTER TABLE ? ENABLE TRIGGER ALL'';

ENABLE TRIGGER ALL ON DATABASE;';

 

-- PRINT @nvcStmt;

 

EXEC sp_executesql @nvcStmt;

2009/08/10 12:16 2009/08/10 12:16
I. Sequel Safe에서 DBA로 지정된 사용자만이 모델을 수정할 수 있습니다.

먼저 Sequel Safe에 국한하여 다음과 같이 용어를 재 정의합니다.

  1. DBA
    1. SQLSafe.dbo.DBAs 테이블에 등록되어 있는 Login을 말합니다.
    2. 모델러 & SQL개발을 담당하는 sysadmin에 속한 사람을 등록합니다.

  2. SQLDeveloper
    1. 개발 네트워크의 개발 DB에 추가되어 있는 DB Role입니다.
    2. 개발 DB에 대해 db_owner 역할에 속하지만, 테이블과 뷰를 생성할 권한은 없습니다.
    3. SQL개발을 담당하는 사람이 이 Role에 속합니다.

  3. Developer
    1. 개발, 테스트 & QA 네크워크의 DB에 추가되어 있는 DB Role입니다.
    2. db_datareader와 db_datawriter 역할에 속합니다.
    3. 모든 SP, UDF, Trigger에 대한 View definition 권한을 가집니다.
    4. 모든 SP에 대한 Execute 권한을 가집니다.
    5. SPExecutor라는 User로 Impersonate (= 가장) 할 권한을 가집니다.
    6. SQL 서버와 연동하는 프로그램을 작성하는 개발자가 이 Role에 속합니다.

  4. AppServer
    1. 개발, 테스트 & QA, 프로덕트 네트워크의 DB에 추가되어 있는 DB Role입니다.
    2. 모든 SP, UDF, Trigger에 대한 View definition 권한을 가집니다.
    3. 모든 SP에 대한 Execute 권한을 가집니다.
    4. SPExecutor라는 User로 Impersonate (= 가장) 할 권한을 가집니다.
    5. SQL 서버에 접속하는 프로그램이 사용할 계정이 이 Role에 속합니다.

      사용자 삽입 이미지




SQLSafe.dbo.DBAs 테이블에 등록되지 않은 사용자가... 테이블이나 뷰에 대한 DDL문을 실행하면, 그 DDL문은 바로 롤백됩니다.


II. 모델 수정 작업은 DDL 스크립트 실행을 통해서만 가능합니다.

테이블 디자이너를 사용하여 모델을 수정할 수 없습니다.

만약 테이블 디자이너를 통해 테이블 변경이나 생성 작업을 한다면, 아래와 같은 에러 메세지가 출력됩니다.

사용자 삽입 이미지



이런 제약을 둔 가장 큰 이유는... DDL 트리거가 sp_rename을 캐치하지 못하기 때문입니다.

아시다시피 테이블 디자이너를 통해 테이블을 수정할 때 sp_rename이 종종 실행되는데... 이렇게 되면 테이블의 버전을 관리하지 못하게 되기 때문에 부득이 이런 제약을 넣었습니다.

따라서, 실행이 차단되어 있진 않지만 sp_rename을 직접 사용하는 일이 있어서는 안됩니다.



III. NOT NULL 속성의 컬럼을 추가하는 경우, 반드시 DEFAULT 제약 조건 사용

개발 DB에서는 테이블이 비어 있어서 NOT NULL 필드를 추가할 수 있었다해도... 배포하는 과정에서는 상황이 달라질 수 있기 때문입니다.

2009/08/10 12:14 2009/08/10 12:14
알고보면 기존 버전에서 계층형 설계에 사용하던 materialized path 개념과 같지만... 코드 작성은 훨씬 편해졌습니다.

이제 개념은 잡았으니... 메서드 목록만 적어 놓으면 될 듯...
GetAncestor()

현재 항목의 n번째 상위 항목을 나타내는 hierarchyid를 반환합니다.

child.GetAncestor(n)

GetDescendant()

부모의 자식 노드를 반환합니다.

parent.GetDescendant (child1, child2)

parent가 NULL인 경우 NULL을 반환합니다.
parent가 NULL이 아니고 child1과 child2가 모두 NULL인 경우 부모의 자식을 반환합니다.
parent와 child1이 NULL이 아니고 child2가 NULL인 경우 child1보다 큰 부모의 자식을 반환합니다.
parent와 child2가 NULL이 아니고 child1이 NULL인 경우 child2보다 작은 부모의 자식을 반환합니다.
parent, child1 및 child2가 NULL이 아닌 경우 child1보다 크고 child2보다 작은 모의 자식을 반환합니다.
child1이 NULL도 아니고 부모의 자식도 아닌 경우 예외가 발생합니다.
child2가 NULL도 아니고 부모의 자식도 아닌 경우 예외가 발생합니다.
child1이 child2보가 크거나 같으면 예외가 발생합니다.

GetLevel()

트리에서 노드의 깊이를 나타내는 정수를 반환합니다.

node.GetLevel()

GetRoot()

계층 트리의 루트를 반환합니다.

hierarchyid::GetRoot()

IsDescendantOf()  BOL의 설명이 잘 못 되어 있어 수정 (2009년 5월 BOL 기준)

자식이 현재 항목의 하위 항목일 경우 true를 반환합니다.

child.IsDescendantOf(parent)

GetReparentedValue()

oldRoot에서 newRoot 노드로 특정 노드의 부모 노드를 변경했을 때 특정 노드가 가져야야하는 새로운 노드를 반환합니다.

node.GetReparentedValue (oldRoot, newRoot)

hierarchyid <-> string 변환

ToString()
Parse()

T-SQL을 사용하여 호출할 수 없는 method

Read()
Write()

2009/08/10 12:11 2009/08/10 12:11
테이블에서 NULL 값을 허용하는 컬럼에 사용하는 옵션으로 SPARSE 가 있습니다. [SQL Server 2008]

SPARSE 컬럼에 NULL 값이 입력되면 저장 공간을 전혀 차지 하지 않지만, NULL이 아닌 값이 저장될 경우에는 4byte의 추가 공간을 필요로합니다.

BOL에서는 SPARSE 컬럼의 사용으로 인해 20% ~ 40% 정도의 공간이 절약될 수 있다면 SPARSE 컬럼을 사용하라고 권고하는군요.

아래 표는 SPARSE 컬럼을 사용했을 때 40%의 공간을 절약하기 위해 필요한 NULL 값 비율을 데이터 타입 별로 나타내고 있습니다.

데이터 타입

NULL 비율

bit                                                             

  98%  

tinyint

86%

smallint

76%

int

64%

bigint

52%

real

64%

float

52%

smallmoney

64%

money

52%

smalldatetime

64%

datetime

52%

uniqueidentifier

43%

date

69%

datetime2(0)

57%

datetime2(7)

52%

time(0)

69%

time(7)

60%

datetimetoffset(0)

52%

datetimetoffset (7)

49%

decimal / numeric(1,s)

60%

decimal / numeric(38,s)

42%

varchar / char

60%

nvarchar / nchar

60%

varbinary / binary

60%

xml

60%

hierarchyid

60%


※ SPARSE 지정이 불가능한 데이터 타입
 : geography, geometry, image, text, ntext, timestamp, UDT



용법 :

CREATE TABLE dbo.Demo (

        docID int IDENTITY NOT NULL PRIMARY KEY,

        title nvarchar(100) NOT NULL,

        spec nvarchar(10) SPARSE NULL,

        location int SPARSE NULL

);



SPARSE 컬럼은 NULL 이 아닌 값을 검색할 때 오버헤드가 있는데, 아래와 같이 NULL이 아닌 값만 필터링하여 인덱스를 생성하면 좋습니다.

CREATE INDEX IX_NN_Demo_location ON dbo.Demo (location) WHERE location IS NOT NULL;

2009/08/10 12:10 2009/08/10 12:10
오늘은 SQL Server 사용자 권한 정책에 대해 얘기 해 보겠습니다.

이하의 내용은 저희 회사에서 제가 사용하는 방법으로... 당연한 얘기지만 이 방법이 모든 경우에 적합하다고 볼 수는 없습니다.


첫번째 고민 : Windows 인증을 사용할까? SQL Server 인증을 사용할까?

일반적인 권고는 Windows 인증입니다.
아무래도 여러사람에 의해 공유되는 SQL Server 인증은 관리면이나 보안면에서 좋지 않을테니까요.
하지만 SQL Server 인증을 아예 사용하지 않는 것도... 현실적으론 어렵더군요.

- Windows 도메인 로그인을 가지고 있는 사람들... DBA, 개발자와 같은 이들에게는 Windows 인증을 사용합니다.
- 웹 서버, 미들웨어 서버 등의 어플리케이션 서버는 SQL Server 인증을 사용합니다.



두번째 고민 : 개발 DB에서 개발자의 권한은 어느 정도가 적당하지?

저는 데이터베이스에 접속해서 개발하는 사람을 세 부류로 나눴습니다.

- 개발 DBA : sysadmin입니다. 해당 데이터베이스에서 작업의 제약을 받지 않습니다.
- SQL 개발자 : db_owner이지만 SP, Function, Trigger를 제외한 다른 개체에대한 DDL문 사용 권한이 없습니다.
- 개발자 : data_reader & data_writer이고, 모든 SP에 대한 Execute와 View Definition 권한이 있습니다.

SQL 개발자와 개발자는 Database Role 개체로 생성한 후, 각 사람의 도메인 로그인을 해당 Role에 매핑하여 관리합니다.

IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE [name]=N'Developer' AND [type]='R')

    CREATE ROLE [Developer] AUTHORIZATION [dbo];

 

IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE [name]=N'SQLDeveloper' AND [type]='R')

    CREATE ROLE [SQLDeveloper] AUTHORIZATION [dbo];

GO

 

EXEC sp_addrolemember N'db_datareader', N'Developer';

EXEC sp_addrolemember N'db_datawriter', N'Developer';

EXEC sp_addrolemember N'db_owner', N'SQLDeveloper';

GO



[Developer] Role이 모든 SP에 대한 Execute 및 View Definition 권한을 갖도록 하기 위해... DDL 트리거를 만들고 아래 구문을 포함시킵니다. 즉, SP가 Create 될 때마다 아래 구문이 실행되도록 합니다.

GRANT VIEW DEFINITION ON OBJECT::[SP이름] TO [Devolper];

GRANT EXECUTE ON OBJECT::[SP이름] TO [Devolper];




세번째 고민 : 어플리케이션 서버용 SQL Server 로그인의 권한은?

사실 권한 정책 자체는 심플합니다. 특정 계정에 필요 이상의 권한을 주지 않는다.

그렇다면 어플리케이션 서버가 가져야하는 권한은 어느 정도일까요?

SP를 Execute할 수 있는 권한 이것 하나만 주고 싶군요.

저는 어플리케이션 서버의 로그인을 [AppServer]라는 Database Role에 속하도록 설정하고, [AppServer] Role은 모든 SP에 대해 Execute 권한을 가지도록 하고 있습니다.

[AppServer] Role이 모든 SP에 대한 Execute 권한을 갖도록 하기 위해... DDL 트리거를 만들고 아래 구문을 포함시킵니다.
 즉, SP가 Create 될 때마다 아래 구문이 실행되도록 합니다.

GRANT EXECUTE ON OBJECT::[SP이름] TO [AppServer];




네번째 고민 : SP를 Execute할 권한이 있는데도 SP 실행이 실패한다.

동적 쿼리를 사용하는 경우입니다.

SP에 대한 실행 권한이 있다해도 동적 쿼리에 포함된 개체에 대해 충분한 권한이 없다면 해당 SP는 실행이 안됩니다.

이런 경우 Execute AS 절을 사용하면 SP를 실행할 때만 충분한 권한이 있는 User로 가장 (impersonate) 시킬 수 있습니다.

SP를 실행할 때 사용할 로그인 및 사용자를 만들어 충분한 권한을 가지도록 하고 각 DB Role이 해당 사용자를 가장할 수 있는 권한을 줍니다.

이 때 생성한 로그인의 패스워드는 GUID를 생성하여 셋팅하는데...
이유는... 누구도 이 계정으로 로그인할 일이 없기 때문입니다.

오로지 SP 실행을 위한 계정일 뿐입니다.

DECLARE @vchPW varchar(50);

 

SET @vchPW = NEWID();

 

IF NOT EXISTS (SELECT * FROM sys.sql_logins WHERE [name] = N'SPExecutor')

    EXEC ('CREATE LOGIN [SPExecutor] WITH PASSWORD=''' + @vchPW + ''', DEFAULT_DATABASE=master;');

GO

 

IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE [name]=N'SPExecutor' AND [type]='S')

    CREATE USER [SPExecutor] FOR LOGIN SPExecutor WITH DEFAULT_SCHEMA=[dbo];

GO

 

EXEC sp_addrolemember 'db_owner', N'SPExecutor';

GO

 

GRANT IMPERSONATE ON USER::SPExecutor TO AppServer;

GRANT IMPERSONATE ON USER::SPExecutor TO Developer;

GRANT IMPERSONATE ON USER::SPExecutor TO SQLDeveloper;

GO




다섯번째 고민 : Execute AS 절을 사용했더니, 데이터베이스 간의 개체 참조가 되지 않는다.

모듈 안에서 Execute AS 절을 사용하는 경우, 다른 데이터베이스에 있는 개체를 참조할 수 없게 되는 문제가 생깁니다.
보안 상의 이슈로 데이터베이스간의 소유권 체인을 불허하는 것이 Default이기 때문이죠.

데이터베이스간 소유권 체인을 허용하는 것은... 상황에 따라 문제가 될 수도 있고 그렇지 않을 수도 있습니다.

문제가 되지 않는다면 TRUSTWORTHY 옵션을 설정하여 데이터베이스간의 소유권 체인을 허용할 수 있는데... 이렇게 하면 Execute AS 절을 사용하더라도 다른 데이터베이스의 개체를 참조할 수 있습니다.
(물론 다른 데이터베이스에도 SPExecutor가 User로 등록되어 있어야 합니다.)

ALTER DATABASE [DB이름] SET TRUSTWORTHY ON;




Sequel Safe에서는 이상의 셋팅이 포함되어 있습니다.
2009/08/10 12:08 2009/08/10 12:08
SQL Server 2008 온라인 설명서가 업데이트 되었습니다.

아래의 경로에서 다운받으실 수 있습니다.

Microsoft SQL Server 2008 온라인 설명서(2009년 5월)
http://www.microsoft.com/downloads/details.aspx?displaylang=ko&FamilyID=765433f7-0983-4d7a-b628-
0a98145bcb97

좋은 하루 되세요.
2009/08/10 10:26 2009/08/10 10:26

1.데이터와 비즈니스 어플리케이션을 잘 알아야 한다.

동일한 정보는 다른 비즈니스 데이터 원천으로부터 검색될 수 있다. 이러한 원천에 익숙해야 한다. 당신은 당신의 데이터베이스 안의 데이터의 크기와 분포를 반드시 알아야 한다. 또한 SQL을 작성하기 전에 비즈니스 개체 안의 관계와 같은 데이터 모델을 전체적으로 이해해야 한다. 이러한 이해는 당신이 여러 테이블에 서 정보를 검색하는데 있어서 보다 좋은 쿼리를 작성할 수 있다. DESIGNER/2000 과 같은 CASE TOOLS은 다른 비즈니스와 데이터베이스 객체사이의 관계를 문서화 하는데 좋은 역할을 한다.

2.실제 데이터를 가지고 당신의 쿼리를 검사하라.

대부분의 조직은 개발, 검사, 제품의 3가지 데이터베이스 환경을 가진다. 프로그래머는 어플리케이션을 만들고 검사하는데 개발 데이터베이스 환경을 사용하는데, 이 어플리케이션이 제품 환경으로 전환되기 전에 프로그래머와 사용자에 의해 검사 환경하에서 보다 엄격하게 검토되어야 한다.



SQL이 검사 환경하에서 테스트될 때, 검사 데이터베이스가 가지고 있는 데이터는 제품 데이터베이스를 반영해야 한다. 비실제적인 데이터를 가지고 테스트된 SQL문은 제품 안에서는 다르게 작동할 수 있다. 엄격한 테스트를 보장하기 위해서는, 검사 환경하에서의 데이터 분포는 반드시 제품 환경에서의 분포와 밀접하게 닮아야 한다.

3.동일한 SQL을 사용하라.

가능한한 BIND VARIABLE, STORED PROCEDURE, PACKAGE의 이점을 활용하라.


IDENTICAL SQL문의 이점은 PARSING이 불필요하기에 데이터베이스 서버안에서 메모리 사용의 축소와 빠른 수행을 포함한다. 예로서 아래의 SQL 문은 IDENTICAL하지 않다.

SELECT * FROM EMPLOYEE WHERE EMPID = 10;
SELECT * FROM EMPLOYEE WHERE EMPID = 10;
SELECT * FROM EMPLOYEE WHERE EMPID = 20;


그러나 I_EMPID라고 이름 주어진 BIND VARIABLE을 사용하면 SQL 문은 이렇게 된다.



SELECT * FROM EMPLOYEE WHERE EMPID = :I_EMPID;

4.주의 깊게 인덱스를 사용하라.

테이블상에 모든 필요한 인덱스는 생성되어야 한다. 하지만 너무 많은 인덱스는 성능을 떨어뜨릴 수 있다. 그러면 어떻게 인덱스를 만들 칼럼을 선택해야 하는가?

*최종 사용자에 의해 사용되는 어플리케이션 SQL과 쿼리의 WHERE 절에서 빈번하게 사용되는 칼럼에 인덱스를 만들어야 한다.

*SQL 문에서 자주 테이블을 JOIN하는데 사용되는 칼럼은 인덱스되어야 한다.

*같은 값을 가지는 ROW가 적은 비율을 가지는 칼럼에 인덱스를 사용하라.

*쿼리의 WHERE 절에서 오직 함수와 OPERATOR로 사용되는 칼럼에는 인덱스를 만들면 안된다.

*자주 변경되거나 인덱스를 만들때 얻는 효율성보다 삽입, 갱신, 삭제로 인해 잃는 효율성이 더 큰 칼럼에는 인덱스를 만들면 안된다. 이러한 OPERATION은 인덱스를 유지하기 위한 필요 때문에 느려진다.

*UNIQUE 인덱스는 더 나은 선택성 때문에 NONUNIQUE 인덱스보다 좋다. PRIMARY KEY 칼럼에 UNIQUE 인덱스를 사용한다. 그리고 FOREIGN KEY 칼럼과 WHERE 절 에서 자주 사용되는 칼럼에는 NONUNIQUE 인덱스를 사용한다.

5.가용한 인덱스 PATH를 만들어라.

인덱스를 사용하기 위해서는 기술한 SQL문을 이용할 수 있는 식으로 SQL을 작성하라. OPTIMIZER는 인덱스가 존재하기 때문에 인덱스를 사용하는 ACESS PATH 를 사용할 수 없다. 따라서 ACCESS PATH는 반드시 SQL이 사용할 수 있게 만들어 져야 한다. SQL HINT를 사용하는 것은 인덱스 사용을 보증해주는 방법중 하나이다. 특정 ACCESS PATH를 선택하기 위한 다음의 힌트를 참고 하라

6.가능하면 EXPLAIN과 TKPROF를 사용하라.

만약 SQL문이 잘 다듬어지지 않았다면 비록 오라클 데이터베이스가 잘 짜여져 있어도 효율성이 떨어질 것이다. 이럴 경우 EXPLAIN TKPROF에 능숙해져야 한다. EXPALIN PLAN은 SQL이 사용하는 ACCESS PATH를 발견할 수 있게 해주고 TKPROF는 실제 PERFORMANEC의 통계치를 보여준다. 이 TOOL은 오라클 서버 소프트웨어에 포함되어 있고 SQL의 성능을 향상시켜 준다.

7.OPTIMIZER를 이해하라.

SQL은 RULE-BASED나 COST-BASED중 하나를 이용해서 기동된다.기존의 소프트웨어는 RULE BASED 방식을 채택하고 있다. 그리고 많은 오라클 소프트웨어가 이러한 방식을 오랫동안 사용해 왔다. 그러나 새로 출시된 소프트웨어에 대해서는 COST BASED 방식의 OPTIMIZER를 고려해야 한다. 오라클은 새로 출시되는 프로그램을 COST BASED방식으로 업그레이드 시켜왔으며 이러한 방식은 시스템을 훨씬 더 안정적으로 만들었다. 만약 COST BASED방식의 OPTIMIZER를 사용한다면 반드시 ANALYZE 스키마를 정기적으로 사용해야 한다. ANALYZE스키마는 데이터베이스 통계를 데이터 사전 테이블에 기록하는 역할을 수행하며 그렇게 되면 COST BASED OPTIMIZER가 그것을 사용하게 된다. SQL은 COST BASED OPTIMIZER를 사용할 때만 잘 조정될 수 있다. 만약
RULE BASED에서 COST BASED로 바꾸고 싶다면 데이터베이스를 사용하는 모든 소프트웨어의 모든 SQL문의 성능을 평가해 보아야 한다.

8.지엽적으로 동작하더라도 전역적으로 생각하라

항상 주의할 것은 하나의 SQL문을 조정하기 위해 생긴 데이터베이스안의 변화는 다른 응용프로그램이나 다른 사용자가 이용하는 다른 명령문에 영향을 미친다는 사실이다.

9.WHERE절은 매우 중요하다.

비록 인덱스가 가용하다고 해도 다음의 WHERE 절은 그 인덱스 ACCESS PATH 를 사용하지 않는다.(즉 COL1 과 COL2는 같은 테이블에 있으며 인덱스는 COL1에 만들어진다.)

COL1 > COL2
COL1 < COL2
COL1 > = COL2
COL1 <= COL2
COL1 IS NULL
COL1 IS NOT NULL.


인덱스는 NULL값을 갖는 칼럼에는 ROWID를 저장하지 않는다. 따라서 NULL값을 갖는 ROW를 검색할 때는 인덱스를 사용하지 못한다.

COL1 NOT IN (VALUE1, VALUE2 )
COL1 != EXPRESSION
COL1 LIKE ''%PATTERN''.

이럴 경우 THE LEADING EDGE OF THE INDEX(?) 는 작동되지 않고 인덱스가 사용되지 못하게 한다. 한편 COL1 LIKE ''PATTERN %''이나 COL1 LIKE ''PATTERN % PATTERN%'' 는 한정된 인덱스 스캔을 수행하기 때문에 인덱스를 사용할 수 있다.

NOT EXISTS SUBQUERY
EXPRESSION1 = EXPRESSION2.


인덱스된 컬럼을 포함하는 표현(EXPRESSION), 함수, 계산(CALCULATIONS)은 인덱스를 사용하지 못한다. 다음의 예에서 보면 UPPER SQL 함수를 사용하면 인덱스 스캔을 사용할 수 없고 FULL TABLE SCAN으로 끝나고 만다.

SELECT DEPT_NAME
FROM DEPARTMENT
WHERE UPPER(DEPT_NAME) LIKE ''SALES%'';


10.레코드 필터링을 위해서는 HAVING보다는 WHERE를 사용하라.

인덱스가 걸려있는 칼럼에는 GROUP BY와 같이 HAVING절을 사용하지 마라. 이 경우 인덱스는 사용되지 않는다. 또한 WHERE절로 된 ROW를 사용하지 마라. 만약 EMP테이블이 DEPTID컬럼에 인덱스를 가지고 있다면 다음 질의는 HAVING 절을 이용하지 못한다.

SELECT DEPTID,
SUM(SALARY)
FROM EMP
GROUP BY DEPTID
HAVING DEPTID = 100;

그러나 같은 질의가 인덱스를 사용하기 위해 다시 씌여질 수 있다.

SELECT DEPTID,
SUM(SALARY)
FROM EMP
WHERE DEPTID = 100
GROUP BY DEPTID;


11. WHERE 절에 선행 INDEX 칼럼을 명시하라.

복합 인덱스의 경우, 선행 인덱스가 WHERE절에 명시되어 있다면 쿼리는 그 인덱스 를 사용할 것이다. 다음의 질의는 PART_NUM과 PRODUCT_ID 칼럼 에 있는 PRIMARY KEY CONSTRAINT에 기초한 복합 인덱스를 이용할 것이다.

SELECT * FROM PARTS WHERE PART_NUM = 100;

반면, 다음의 쿼리는 복합인덱스를 사용하지 않는다.

SELECT * FROM PARTS WHERE PRODUCT_ID = 5555;

같은 요청(REQUEST)이 인덱스를 이용하기 위해 다시 씌어 질 수 있다. 다음 질의의 경우, PART_NUM컬럼은 항상 0 보다 큰 값을 가질것이다.

SELECT * FROM PARTS WHERE PART_NUM > 0 AND PRODUCT_ID = 5555;

12.인덱스 SCAN과 FULL TABLE SCAN을 평가하라.

한 행(ROW)의 15% 이상을 검색하는 경우에는 FULL TABLE SCAN이 INDEX ACESS PATH보다 빠르다. 이런 경우, SQL이 FULL TABLE SCAN을 이용할 수 있도록 여러분 스스로 SQL을 작성하라. 다음의 명령문은 비록 인덱스가 SALARY COLUMN에 만들어져 있어도 인덱스 SCAN을 사용하지 않을 것이다. 첫 번째 SQL 에서, FULL HINT를 사용한다면 오라클은 FULL TABLE SCAN을 수행할 것이다. 인덱 스의 사용이 나쁜 점이 더 많다면 아래의 기술을 이용해서 인덱스 수행을 막을
수 있다.

SELECT * --+FULL FROM EMP WHERE SALARY = 50000;
SELECT * FROM EMP WHERE SALARY+0 = 50000;

다음의 명령문은 비록 인덱스가 SS# COLUMN에 있어도 인덱스 SCAN을 사용하지 않을 것이다.

SELECT * FROM EMP WHERE SS# || '' '' = ''111-22-333'';

오라클이 불분명한 데이터 변환을 수행해야 하는 경우 인덱스가 항상 사용되지 않는 것은 아니다. 다음의 예를 보면, EMP 칼럼에 있는 SALARY는 숫자형 칼럼이고 문자형이 숫자값으로 변환된다.

SELECT * FROM EMP WHERE SALARY = ''50000'';

테이블의 행이 15%이거나 그보다 작을 경우 인덱스 스캔은 보다 잘 수행 될 것이다. 왜냐 하면 인덱스 스캔은 검색된 행(ROW)하나 하나 마다 다중의 논리적인 읽기 검색(READ)을 할 것이기 때문이다. 그러나 FULL TABLE SCAN은 하나의 논리적인 읽기 검색 영역 안의 BLOCK에 있는 모든 행들을 읽을 수 있다. 그래서 테이블의 많은 행들에 접근해야 하는 경우에는 FULL TABLE SCAN이 낫다. 예로 다음의 경우를 보자. 만약 EMP TABLE과 그 테이블의 모든 인덱스에 대해 ANALYZE라
는 명령어가 수행된다면, 오라클은 데이터 사전인 USER_TABLES와 USER_INDEXES에 다음과 같은 통계치를 산출해 낸다.

TABLE STATISTICS:
NUM_ROWS = 1000
BLOCKS = 100

INDEX STATISTICS:

BLEVEL = 2
AVG_LEAF_BLOCKS_PER_KEY = 1
AVG_DATA_BLOCKS_PER_KEY = 1


이러한 통계치 에 근거해서, 아래에 보이는 것이 각각의 다른 SCAN에 대한 논리
적인 읽기(READ)-즉 ACESS된 BLOCK이 될 것이다.

USE OF INDEX TO RETURN ONE ROW = 3

(BLEVEL+(AVG_LEAF_BLOCKS_PER_KEY - 1) + AVG_DATA_PER_KEY

FULL TABLE SCAN = 100
(BLOCKS)


USE OF INDEX TO RETURN ALL ROWS = 3000
(NUM_ROWS * BLOCKS ACCESSED TO RETURN ONE ROW USING INDEX)


13. 인덱스 스캔에 ORDER BY를 사용하라.

오라클의 OPTIMIZER는 , 만약 ORDER BY라는 절이 인덱스된 칼럼에 있다면 인덱스 스캔을 사용할 것이다. 아래의 질의는 이러한 점을 보여 주는 것인데 이 질의는 비록 그 칼럼이 WHERE 절에 명시되어 있지 않다고 해도 EMPID컬럼에 있는 가용한 인덱스를 사용할 것이다. 이 질의는 인덱스로부터 각각의 ROWID를 검색하고 그 ROWID를 사용하는 테이블에 접근한다.

SELECT SALARY FROM EMP ORDER BY EMPID;

만약 이 질의가 제대로 작동하지 않는다면, 당신은 위에서 명시되었던 FULL HINT 를 사용하는 같은 질의를 다시 작성함으로써 다른 대안들을 이용해 볼 수 있다.

14. 자신의 데이터를 알아라

내가 이미 설명한 것처럼, 당신은 당신의 데이터를 상세하게 알고 있어야 한다.
예를 들어 당신이 BOXER라는 테이블을 가지고 있고 그 테이블이 유일하지 않은 인덱스를 가진 SEX라는 컬럼과 BOXER_NAME이라는 두 개의 테이블을 가지고 있다고 가정해 보자. 만약 그 테이블에 같은 수의 남자, 여자 복서가 있다면 오라클이 FULL TABLE SCAN을 수행하는 경우 다음의 질의가 훨씬 빠를 것이다.

SELECT BOXER_NAME FROM BOXER WHERE SEX = ''F'';

당신은 다음과 같이 기술함으로써 질의가 FULL TABLE SCAN을 수행하는지를 확실 하게 해 둘 수 있다.

SELECT BOXER_NAME --+ FULL FROM BOXER WHERE SEX = ''F'';

만약 테이블에 980 명의 남성 복서 데이터가 있다면, 질의는 인덱스 SCAN으로 끝나기 때문에 아래형식의 질의가 더 빠를 것이다.

SELECT BOXER_NAME --+ INDEX (BOXER BOXER_SEX) FROM BOXER


WHERE SEX = ''F'';

이 예는 데이터의 분포에 대해 잘 알고 있는 것이 얼마나 중요한 가를 예시해 준다. 데이터가 많아지고(GROW) 데이터 분포가 변화하는 것처럼 SQL 도 매우 다양할 것이다. 오라클은 OPTIMIZER 가 테이블에 있는 데이터의 분포를 잘 인식하고 적절한 실행 계획을 선택하도록 하기 위해 오라클 7.3 에 HISTOGRAMS라는 기능을 추가했다.

15. KNOW WHEN TO USE LARGE-TABLE SCANS.

작거나 큰 테이블에서 행들을 추출할 때, 전체 테이블의 검색은 인텍스를 사용한 검색보다 성능이 더 좋을 수도 있다. 매우 큰 테이블의 인덱스 검색은 수많은 인덱스와 테이블 블록의 검색이 필요할수도 있다. 이러한 블록들이 데이터베이스 버퍼 캐쉬에 이동되면 가능한한 오래도록 그곳에 머무른다. 그래서 이러한 블록들이 다른 질의등에 필요하지 않을 수도 있기 때문에, 데이터베이스 버퍼 히
트 비율이 감소하며 다중 사용자 시스템의 성능도 저하되기도 한다. 그러나 전체 테이블 검색에 의해서 읽혀진 블록들은 데이터베이스 버퍼 캐쉬에서 일찍 제 거가 되므로 데이터베이스 버퍼 캐쉬 히트 비율은 영향을 받지 않게 된다.

16. MINIMIZE TABLE PASSES.

보통, SQL질의시 참조하는 테이블의 숫자를 줄임으로 성능을 향상시킨다. 참조
되는 테이블의 숫자가 적을수록 질의는 빨라진다. 예를 들면 NAME, STATUS,
PARENT_INCOME, SELF_INCOME의 네개의 컬럼으로 이루어진 학생 테이블
에서 부모님에 의존하는 학생과 독립한 학생의 이름과 수입에 대해서 질의시, 이
학생 테이블을 두번 참조하여 질의하게 된다.



SELECT NAME, PARENT_INCOME FROM STUDENT WHERE STATUS = 1
UNION


SELECT NAME, SELF_INCOME FROM STUDENT WHERE STATUS = 0;



( NAME이 프라이머리 키이며, STATUS는 독립한 학생의 경우는 1, 부모님에
의존적인 학생은 0으로 표시한다)
위의 같은 결과를 테이블을 두번 참조하지 않고도 질의 할 수 있다.

SELECT NAME,PARENT_INCOME*STATUS + SELF_INCOME(1-STATUS)
FROM STUDENT;


17. JOIN TABLES IN THE PROPER ORDER.

다수의 테이블 조인시 테이블들의 조인되는 순서는 매우 중요하다. 전반적으로, 올바른 순서로 테이블이 조인되었다면 적은 수의 행들이 질의시 참조된다. 언제나 다수의 조인된 테이블들을 질의시 우선 엄격하게 조사하여 행들의 숫자를 최대한으로 줄인다. 이러한 방법으로 옵티마이저는 조인의 차후 단계에서 적은 행들을 조사하게 된다. 뿐만 아니라, 여러 조인을 포함하는 LOOP JOIN에서는 가장 먼저 참조되는 테이블(DRIVING TABLE)이 행들을 최소한으로 리턴하도록 해야 한다. 그리고, 마스터와 상세 테이블 조인시에는(예를 들면 ORDER & ORDER LINE ITEM TABLES) 마스터 테이블을 먼저 연결 시켜야 한다.



규칙에 근거한 옵티마이저의 경우에는 FROM CLAUSE의 마지막 테이블이 NESTED LOOP JOIN의 DRIVING TABLE이 된다. NESTED LOOP JOIN이 필요한 경우에는 LOOP의 안쪽의 테이블에는 인텍스를 이용하는 것을 고려할 만하다. EXPLAIN PLAN과 TKPROF는 조인 타입, 조인 테이블 순서, 조인의 단계별 처리된 행들 의 숫자들을 나타낸다.



비용에 근거한 옵티마이저의 경우에는 WHERE CLAUSE에 보여지는 테이블의 순서는 옵티마이저가 가장 최적의 실행 계획을 찾으려고 하는 것과 상관 없다. 조인되는 테이블의 순서를 통제하기 위해서 ORDERED HINT를 사용하는 것이 낫다.

SELECT ORDERS.CUSTID, ORDERS.ORDERNO,
ORDER_LINE_ITEMS.PRODUCTNO --+ORDERED
FROM ORDERS, ORDER_LINE_ITEMS
WHERE ORDERS.ORDERNO = ORDER_LINE_ITEMS.ORDERNO;


18. USE INDEX-ONLY SEARCHES WHEN POSSIBLE.

가능하다면, 인덱스만을 이용하여 질의를 사용하라. 옵티마이저는 오직 인덱스만을 찾을 것이다. 옵티마이저는 SQL을 만족시키는 모든 정보를 인덱스에서 찾을 수 있을 때, 인덱스만을 이용할 것이다. 예를들면, EMP테이블이 LANME과 FNAME의 열에 복합 인덱스를 가지고 있다면 다음의 질의는 인덱스만은 이용할 것이다.

SELECT FNAME FROM EMP WHERE LNAME = ''SMITH'';

반면에 다음의 질의는 인덱스와 테이블을 모두 참조한다.

SELECT FNAME , SALARY FROM EMP WHERE LNAME = ''SMITH'';

19. REDUNDANCY IS GOOD.

WHERE CLAUSE에 가능한한 많은 정보를 제공하라. 예를 들면 WHERE COL1 = COL2 AND COL1 = 10이라면 옵티마이저는 COL2=10이라고 추론하지만, WHERE COL1 = COL2 AND COL2 = COL3이면 COL1=COL3이라고 초론하지는 않는다.

20. KEEP IT SIMPLE, STUPID.

가능하면 SQL문을 간단하게 만들라. 매우 복잡한 SQL문은 옵티마이저를 무력화시킬 수도 있다. 때로는 다수의 간단한 SQL문이 단일의 복잡한 SQL문보다 성능이 좋을 수도 있다. 오라클의 비용에 근거한 옵티마이저는 아직은 완벽하지 않다. 그래서 EXPLAIN PLAN에 주의를 기울여야 한다. 여기서 비용이란 상대적인 개념이기에 정확히 그것이 무엇을 의미하는지 알지 목한다. 하지만 분명한 것은 적은 비용이 보다 좋은 성능을 의미한다는 것이다.



종종 임시 테이블을 사용하여 많은 테이블들을 포함하는 복잡한 SQL 조인을 쪼개는 것이 효율적일 수도 있다. 예를 들면, 조인이 대량의 데이터가 있는 8개의 테이블을 포함할 때, 복잡한 SQL을 두 세개의 SQL로 쪼개는 것이 낫을 수 있다. 각각의 질의는 많아야 네개정도의 테이블들을 포함하며 그 중간 값을 저장 하는 것이 낫을 수 있다.

21. YOU CAN REACH THE SAME DESTINATION IN DIFFERENT WAYS.

많은 경우에, 하나 이상의 SQL문은 의도한 같은 결과를 줄 수 있다. 각각의 SQL은 다른 접근 경로를 사용하며 다르게 수행한다. 예를들면, MINUS(-) 산술자는 WHERE NOT IN (SELECT ) OR WHERE NOT EXISTS 보다 더 빠르다.


예를들면, STATE와 AREA_CODE에 각각 다른 인덱스가 걸려 있다. 인덱스에도 불구하고 다음의 질의는 NOT IN의 사용으로 인해 테이블 전체를 조사하게 된다.



SELECT CUSTOMER_ID FROM CUSTOMERS WHERE STATE IN (''VA'', ''DC'', ''MD'')
AND AREA_CODE NOT IN (804, 410);


그러나 같은 질의가 다음 처럼 쓰여진다면 인덱스를 사용하게 된다.



SELECT CUSTOMER_ID FROM CUSTOMERS WHERE STATE IN (''VA'', ''DC'', ''MD'')
MINUS SELECT CUSTOMER_ID FROM CUSTOMERS WHERE AREA_CODE IN (804, 410);

WHERE절에 OR을 포함한다면 OR대신에 UNION을 사용할 수 있다. 그래서, SQL 질의를 수행하기 전에 먼저 실행계획을 조심스럽게 평가해야 한다. 이러한 평가는 EXPLAIN PLAN AND TKPROF를 이용하여 할 수 있다.

22. USE THE SPECIAL COLUMNS.

ROWID AND ROWNUM 열을 이용하라. ROWID를 이용하는 것이 가장 빠르다.
예를들면, ROWID를 이용한 UPDATE는 다음과 같다.

SELECT ROWID, SALARY INTO TEMP_ROWID, TEMP_SALARY FROM EMPLOYEE;

UPDATE EMPLOYEE SET SALARY = TEMP_SALARY * 1.5


WHERE ROWID = TEMP_ROWID;

ROWID값은 데이터베이스에서 언제나 같지는 않다. 그래서, SQL이나 응용 프로그램이용시 ROWID값을 절대화 시키지 말라. 리턴되는 행들의 숫자를 제한시키기위해 ROWNUM을 이용하라. 만약에 리턴되는 행들을 정확히 모른다면 리턴되는 행들의 숫자를 제한하기위해 ROWNUM을 사용하라
다음의 질의는 100개 이상의 행들을 리턴하지는 않는다.



SELECT EMPLOYE.SS#, DEPARTMENT.DEPT_NAME
FROM EMPLOYEE, DEPENDENT
WHERE EMPLOYEE.DEPT_ID = DEPARTMENT.DEPT_ID
AND ROWNUM < 100;


23.함축적인 커서대신 명시적인 커서를 사용하라.

함축적 커서는 여분의 FETCH를 발생시킨다. 명시적 커서는 DECLARE, OPEN, FETCH와 CLOSE CURSOR문을 사용하여 개발자에 의해서 생성된다. 함축 커서는 DELETE, UPDATE, INSERT와 SELECT문을 사용하면 오라클에 의해서 생성된다.

24.오라클 병렬 쿼리 옵션을 찾아서 이용하라.

병렬 쿼리 옵션을 사용하면, 보다 빠른 성능으로 SQL을 병렬로 실행할 수 있다.
오라클 7에서는, 오직 FULL TABLE SCAN에 기반한 쿼리만이 병렬로 수행될 수 있다.
오라클 8에서는, 인덱스가 분할되어있다면 INDEXED RANGE SCANS에 기반한 쿼리도 병렬로 처리될 수 있다. 병렬 쿼리 옵션은 다수의 디스크 드라이버를 포함하는 SMP와 MPP SYSTEM에서만 사용될 수 있다.

오라클 서버는 많은 우수한 특성을 가지고 있지만, 이러한 특성의 존재만으로는 빠른 성능을 보장하지 않는다. 이러한 특성을 위해서 데이터베이스를 조정해야하며 특성을 이용하기 위해 특별하게 SQL을 작성해야 한다. 예를 들면, 다음의 SQL은 병렬로 수행될 수 있다.

SELECT * --+PARALLEL(ORDERS,6) FROM ORDERS;

25. 네트웍 소통량을 줄이고 한번에 처리되는 작업량을 늘려라.

ARRAY PROCESSING과 PL/SQL BLOCK을 사용하면 보다 나은 성능을 얻을 수 있고 네트웍 소통량을 줄인다. ARRAY PROCESSING은 하나의 SQL문으로 많은 ROW를 처리할 수 있게 한다. 예를 들면, INSERT문에서 배열을 사용하면 테이블내의 1,000 ROW를 삽입할 수 있다. 이러한 기술을 사용하면 주요한 성능 향상을 클라이언트/서버와 배치시스템에서 얻어질 수 있다.

복합 SQL문은 과도한 네트웍 소통을 유발할 수 있다. 그러나 만일 SQL문이 단일 PL/SQL 블록안에 있다면, 전체 블록은 오라클 서버에 보내져서 그곳에서 수행되고, 결과는 클라이언트의 APPLICATION에게 돌아온다.

개발자와 사용자는 종종 SQL을 데이터베이스에서 데이터를 검색하고 전송하는 간단한 방법으로 사용한다. 때때로 직접적으로 SQL을 작성하지 않고 코드 발생기를 사용하여 작성한 APPLICATION은 심각한 성능 문제를 일으킨다. 이러한 성능감퇴는 데이터베이스가 커지면서 증가한다.

SQL은 유연하기 때문에, 다양한 SQL문으로 같은 결과를 얻을 수 있다. 그러나 어떤 문은 다른 것보다 더 효율적이다. 여기에 기술된 팁과 기법을 사용하면 빠르게 사용자에게 정보를 제공할 수 있는 APPLICATION과 리포트를 얻을 수 있다.

2009/08/07 21:56 2009/08/07 21:56

사용자 삽입 이미지
에러:

Windows 2003,  "라이센스를 제공할 터미널서버 라이센스서버가 없으므로 원격 연결이 끊어졌습니다


원인:

터미널 서비스를 설치하실때 응용프로그램모드가 아닌 관리모드로 설치하셔야 한다.
응용프로그램모드는 라이센스가 있어야 사용가능하며 라이센스 없이는 90일 정도만 사용할 수 있다.

Windows 2000에서는 설치시 두 모드중 하나를 선택하게 했지만 Windows 2003에서는 응용프로그램모드로 기본 설치가 된다.


해결책:

관리모드로 변경하시려면..

제어판-시스템-원격 탭에서 원격데스크톱의 "사용자가 이 컴퓨터에 원격으로 연결할수 있음"에 체크한다

체크를 해야 관리모드로 변경된다.

일단 연결을 해야하는데 급할때는 서버의 날짜를 1년전으로 돌리면 사용가능하다.

 

그래도.. 해결이 안되면.. 넷미팅 등의 다른 서비스의 원격기능을 이용해서 접속한다 ^^;

2009/08/01 10:44 2009/08/01 10:44

Microsoft Visual Studio 2005 Service Pack 1 설치 시 , Windows Server 2003에서는
"이 제품에 대한 설치 원본을 사용할 수 없습니다. 원본이 있는지 또는 액세스할 수 있는지 확인하십시오."라는 에러 메시지를 만날 수 있다.


1. 관리 도구 - 로컬 보안 정책
2. [소프트웨어 제한 정책] 마우스 오른쪽 버튼 클릭 -> 새 소프트웨어 제한 정책
3. [강요] 마우스 오른쪽 버튼 클릭 -> 속성
4. [로컬 관리자를 제외한 모든 사용자] 선택 -> 확인
5. Microsoft Visual Studio 2005 Service Pack 1 설치
6. [소프트웨어 제한 정책] 마우스 오른쪽 버튼 클릭 -> 소프트웨어 제한 정책 삭제

2009/08/01 10:43 2009/08/01 10:43

쿼리분석기에서 아래의 명령을 수행한다



use DB_NAME


--분리된 사용자 찾기

exec sp_change_users_login 'Report'

--현재 데이터베이스에서 어떠한 로그인에도 연결되지 않은 사용자와 해당 SID(보안 ID)를 나열


--연결하고자 하는 유저를 하나씩 아래 프로시저로 실행한다.
exec sp_change_users_login 'Update_One','LOGIN_NAME','LOGIN_NAME'



--자동으로 모두 연결하려면 아래 프로시저를 실행한다.

exec sp_change_users_login 'Auto_Fix', 'LOGIN_NAME'

2009/08/01 10:31 2009/08/01 10:31
MS - SQL에서 도스 명령어를 실행할 수 있습니다.

바로 xp_cmdshell 을 통해서죠.

간단히 말하면 xp_cmdshell는 도스 명령어를 실행할 수 있게 해주는 프로시저입니다.

다음은 디렉터리 명령을 실행하는 xp_cmdshell 확장 저장 프로시저를 보여 주는 예제입니다.
EXEC master..xp_cmdshell 'dir *.exe'

(참고, 기본적으로 디렉토리의 시작은 C:\WINNT\system32\ 입니다.
그러니 저 명령어는 C:\WINNT\system32\*.exe 파일을 찾겠네요.

또 다른 예를 볼까요?

xp_cmdshell 'del C:\TEST.CSV'
이렇게 하면 해당 파일을 찾아서 지워줍니다. 파일이 없으면 파일이 없다고 결과값을 반영하고,
별 에러없이 지워졌으면 NULL결과값을 반영합니다.

우와 잘못하다간 C를 통째로 날려 버릴수도 있겠네요.. 즉 QA랑 db계정만 알고 있으면
해킹은 간단합니다. 예전에 MS-SQL 7.0 일 경우에는 설치할 때 sa의 패스워드를 설치시 묻지도 않아서 ODBC를 통한 해킹도 쉽게 가능했습니다.

다음은 MSDN의 좀 더 실질적인 예제입니다.
사용자에게 net send를 사용하여 SQL Server가 곧 종료된다는 것을 알리고 net pause를 사용하여 서버를 일시 중지한 다음, net stop을 사용하여 서버를 종료합니다.

CREATE PROC shutdown10
AS
EXEC xp_cmdshell 'net send /domain:SQL_USERS ''SQL Server shutting down
in 10 minutes. No more connections allowed.', no_output
EXEC xp_cmdshell 'net pause sqlserver'
WAITFOR DELAY '00:05:00'
EXEC xp_cmdshell 'net send /domain: SQL_USERS ''SQL Server shutting down
in 5 minutes.', no_output
WAITFOR DELAY '00:04:00'
EXEC xp_cmdshell 'net send /domain:SQL_USERS ''SQL Server shutting down
in 1 minute. Log off now.', no_output
WAITFOR DELAY '00:01:00'
EXEC xp_cmdshell 'net stop sqlserver', no_output



이런것 만들어 두면 편하겠죠?


xp_cmdshell 프로시저를 사용하면 다양하게 응용할 수 있습니다. 
2009/08/01 10:30 2009/08/01 10:30

-- MS-SQL 약식 테이블 명세서 보기(쿼리문)

-- 테이블명, 번호, 컬럼명, 테이터 타입, 데이터 크기, NULL여부, 기본값  순으로 출력 됨

-- 쿼리 분석기에서 아래의 SQL 문을 실행하고, 출력된 결과를 마우스 드레그를 통해 복사한 후 엑셀로 정리 가능


SELECT TABLE_NAME, ORDINAL_POSITION, COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, IS_NULLABLE, COLUMN_DEFAULT
FROM INFORMATION_SCHEMA.COLUMNS
ORDER BY TABLE_NAME, ORDINAL_POSITION 

2009/08/01 10:28 2009/08/01 10:28

쿼리분석기, Enterprise Manager, SQL Server Management Studio 등의 툴에서

기본 포트가아닌 포트로 MSSQL을 접속 할 때,

일반적으로 사용하는 ":" 대신 ","로 포트 구분 해 줘야 함


예)
123.123.123.123:9999 (X)

123.123.123.123,9999 (O)

2009/08/01 10:28 2009/08/01 10:28

저장프로시저에서 테이블명은 변수로 받아서 바로 쓰지 못한다.

동적 쿼리에서 몇가지 조건의 경우는 오류 메시지가 나는데,

테이블명을 동적으로 받아올때가 그 중 하나이다.

동적 쿼리를 사용하면 DBMS가 미리 실행 계획을 준비해놓기 힘들기 때문에 작업 효율에 문제가 생기므로 일반적인 경우는 동적 쿼리를 자제하는 것이 좋다.

몇가지 관리 목적에서 동적 쿼리를 사용해야만 한다면, sp_executesql 를 사용하면 된다.


ex)

CREATE PROC test
 @게시판 VARCHAR(128)
AS
 DECLARE @sql NVARCHAR(512)

 SET @sql = 'SELECT * '
 SET @sql = @sql + ' FROM ' + @게시판
 SET @sql = @sql + ' ORDER BY idx DESC '

 EXEC sp_executesql @sql
GO

2009/08/01 10:27 2009/08/01 10:27

한개의 테이블에 고유키 없이 중복된 데이터가 들어가 있을 경우 불필요한 중복 데이터 삭제 방법


우선, 테이블 디자인 수정에서 필드 하나를 추가 한다.

타입은 int 로 주고, 속성은 일련번호로 주면 각 필드마다 일련번호 숫자가 알아서 들어간다.


추가한 필드의 이름이 idx 일 경우 아래의 형식대로 쿼리를 날리면 중복데이터는 한개씩만 남고 사라진다.


DELETE FROM 테이블명 WHERE (NOT EXISTS
   (SELECT idx
   FROM (SELECT MIN(idx) idx
      FROM 테이블명
      GROUP BY 중복컬럼명) X
   WHERE 테이블명.idx = X.idx))

쿼리 날리기전 백업은 기본!!

 
2009/08/01 10:27 2009/08/01 10:27
윈도우 시스템을 운영하다 보면, 원인모를 시스템 다운 현상이 나타날 수 있을 거다.
결국 시스템이 멈춘 현상이 나타나거나 자동으로 재부팅을 하게 되는데, 그럴 경우 얼마동안은 문제 없이 작동을 하게 된다. 이렇게 꾸준하게 반복 되다보면 어딘가 문제의 원인을 찾아야 하는데 이때 쓰는 도구가 성능모니터이다. 디스크, 메모리, 프로세서, 네트워크 등을 살필 수 있으며 장기적인 문제 원인을 찾을 수 있을 거다.
예전에 비해 시스템 성능이 너무 좋아졌기 때문에 시스템 부하로 문제되는 경우는 다소 줄었다.

이 자료는 "윈도우 서버 성능 평가' 자료를 발췌했다.

하드 디스크 병목 현상

디스크 시스템은 서버에서 프로그램 및 데이터를 저장하고 처리하므로 디스크 사용량 및 속도에 영향을 미치는 병목 현상은 서버의 전체적인 성능에 큰 영향을 줍니다.
디 스크 개체가 서버에서 비활성화된 경우 명령줄 도구 Diskperf를 통해 활성화해야 합니다. 또한 % Disk Time은 100%를 초과할 수 있으므로 대신 % Idle Time, Avg. Disk sec/Read 및 Avg. Disk sec/write를 사용하면 하드 디스크가 얼마나 많이 사용되고 있는지 좀더 정확하게 파악할 수 있습니다. % Disk Time에 대한 자세한 내용은 support.microsoft.com/kb/310067 기술 자료 문서를 참조하십시오.

다음은 Microsoft Service Support 엔지니어가 디스크 모니터링을 위해 사용하는 카운터입니다.

  • LogicalDisk\% Free Space 선 택한 논리 디스크 드라이브에서 사용할 수 있는 공간의 백분율을 측정합니다. 이 카운터가 15% 아래로 떨어지면 OS에서 중요 파일을 저장하기 위한 여유 공간이 부족할 수 있습니다. 이 경우 확실한 해결책은 디스크 공간을 늘리는 것입니다.
  • PhysicalDisk\% Idle Time 샘플 간격 중 디스크가 유휴 상태였던 시간 백분율을 측정합니다. 이 카운터가 20% 아래로 떨어지면 디스크 시스템이 포화 상태인 것입니다. 현재 디스크 시스템을 더 빠른 디스크 시스템으로 교체하는 것이 좋습니다.
  • PhysicalDisk\Avg. Disk Sec/Read 디스크에서 데이터를 읽는 데 걸리는 평균 시간(초)을 측정합니다. 값이 25ms(밀리초)보다 크면 디스크에서 읽을 때 디스크 시스템에 지연 현상이 발생하고 있음을 의미합니다. SQL Server® 및 Exchange Server를 호스팅하는 중요 업무 서버의 경우 허용 가능한 임계값은 10ms 미만입니다. 여기에서 가장 현명한 해결책은 현재 디스크 시스템을 더 빠른 디스크 시스템으로 교체하는 것입니다.
  • PhysicalDisk\Avg. Disk Sec/Write 디 스크에 데이터를 쓰는 데 걸리는 평균 시간을 측정합니다. 이 시간이 25ms보다 크면 디스크에 쓸 때 디스크 시스템에 지연 현상이 발생하고 있음을 의미합니다. SQL Server 및 Exchange Server를 호스팅하는 중요 업무 서버의 경우 허용 가능한 임계값은 10ms 미만입니다. 여기에서 현명한 해결책은 디스크 시스템을 더 빠른 디스크 시스템으로 교체하는 것입니다.
  • PhysicalDisk\Avg. Disk Queue Length 얼마나 많은 I/O 작업이 하드 드라이브를 사용할 수 있을 때까지 대기하고 있는지 나타냅니다. 여기에서 값이 스핀들 수 + 2보다 크면 디스크 자체에 병목 현상이 있음을 의미합니다.
  • Memory\Cache Bytes 파일 시스템 캐시에 사용되고 있는 메모리의 양을 나타냅니다. 이 값이 200MB보다 크면 디스크 병목 현상이 발생할 수 있습니다.


메모리 병목 현상

메모리 부족은 대체로 RAM 부족, 메모리 누수 또는 boot.ini의 메모리 스위치 등으로 인해 발생합니다. 메모리 카운터를 소개하기 전에 먼저 /3GB 스위치에 대해 설명하겠습니다.
메모리가 많을수록 디스크 I/O 작업이 줄고 응용 프로그램 성능이 높아집니다. /3GB 스위치는 사용자 모드 프로그램에 더 많은 메모리를 제공하기 위한 방법으로 Windows NT®에서 도입되었습니다.
Windows 에서는 4GB의 가상 주소 공간을 사용하며 이는 시스템의 물리적 RAM과는 무관합니다. 기본적으로 하위 2GB는 사용자 모드 프로그램을 위해 사용되고, 상위 2GB는 커널 모드 프로그램을 위해 사용됩니다. /3GB 스위치를 사용하면 사용자 모드 프로세스에 3GB가 제공됩니다. 그러면 물론 커널 메모리가 가상 주소 공간의 1GB만 남게 되므로 영향을 받습니다. 이 경우 페이징되지 않은 바이트 풀링, 페이징된 바이트 풀링, 사용 가능한 시스템 페이지 테이블 항목 및 데스크톱 힙이 모두 이 1GB 공간 안에 들어가야 하므로 문제가 발생할 수 있습니다. 따라서 /3GB 스위치는 해당 환경에서 충분한 테스트를 거친 후에만 사용해야 합니다.

메모리 관련 병목 현상이 발생하는 경우 이 스위치를 의심해 볼 수 있습니다. /3GB 스위치가 문제의 원인이 아니라면 다음 카운터를 사용하여 잠재적인 메모리 병목 현상을 진단할 수 있습니다.

  • Memory\% Committed Bytes in Use 커밋된 바이트와 커밋 한도의 비율, 즉 가상 메모리의 사용량을 측정합니다. 이 값이 80%보다 크면 메모리가 부족함을 나타냅니다. 이 경우 확실한 해결책은 메모리를 추가하는 것입니다.
  • Memory\% Available Mbytes 프 로세스 실행을 위해 사용할 수 있는 실제 메모리의 양(메가바이트)을 측정합니다. 이 값이 총 물리적 RAM의 5%보다 작으면 메모리가 부족함을 나타내며 이로 인해 페이징 작업이 늘어날 수 있습니다. 이 문제를 해결하려면 메모리를 추가해야 합니다.
  • Memory\Free System Page Table Entries 시스템에서 현재 사용되지 않는 페이지 테이블 항목의 수를 나타냅니다. 이 숫자가 5,000보다 작으면 메모리 누수가 있을 수 있습니다.
  • Memory\Pool Non-Paged Bytes 페 이징되지 않은 풀의 크기(바이트)를 측정합니다. 디스크에 쓸 수 없고 대신 실제 메모리에 남아 있어야 하는 할당된 개체에 대한 시스템 메모리 영역입니다. 이 값이 175MB(또는 /3GB 스위치의 경우 100MB)보다 크면 메모리 누수 가능성이 있습니다. 일반적인 이벤트 ID 2019가 시스템 이벤트 로그에 기록됩니다.
  • Memory\Pool Paged Bytes 페 이징된 풀의 크기(바이트)를 측정합니다. 사용되고 있지 않을 때 디스크에 쓸 수 있는 개체에 대한 시스템 메모리 영역입니다. 이 값이 250MB(또는 /3GB 스위치의 경우 170MB)보다 크면 메모리 누수 가능성이 있습니다. 일반적인 이벤트 ID 2020이 시스템 이벤트 로그에 기록됩니다.
  • Memory\Pages per Second 하드 페이지 결함을 해결하기 위해 디스크에서 페이지를 읽거나 쓰는 속도를 측정합니다. 과도한 페이징으로 인해 이 값이 1,000보다 크면 메모리 누수 가능성이 있습니다.

프로세서 병목 현상

프로세서 병목 현상은 프로세서 자체의 성능이 나빠서 발생하거나 비효율적인 응용 프로그램으로 인해 발생할 수 있습니다. 실제 메모리 부족으로 인해 프로세서가 페이징에서 많은 시간을 보내지 않는지 다시 확인해야 합니다. 잠재적인 프로세서 병목 현상을 조사할 때 Microsoft Service Support 엔지니어는 다음 카운터를 사용합니다.
  • Processor\% Processor Time 프로세서가 비유휴 스레드 실행에 소비하는 경과 시간의 백분율을 측정합니다. 이 백분율이 85%보다 크면 프로세서에 병목 현상이 발생하고 서버에 더 빠른 프로세서가 필요할 수 있습니다.
  • Processor\% User Time 프 로세서가 사용자 모드에서 소비하는 경과 시간의 백분율을 측정합니다. 이 값이 높으면 서버에서 응용 프로그램이 많이 실행되고 있음을 나타냅니다. 한 가지 가능한 해결책은 프로세서 리소스를 많이 사용하는 응용 프로그램을 최적화하는 것입니다.
  • Processor\% Interrupt Time 지정된 샘플 간격 중 프로세서가 하드웨어 인터럽트 수신 및 서비스 제공에 소비하는 시간을 측정합니다. 이 값이 15%보다 크면 하드웨어 문제일 수 있습니다.
  • System\Processor Queue Length 프로세서 큐의 스레드 수를 나타냅니다. 이 값이 일정 기간 동안 CPU 수 x 2보다 크면 서버에 프로세서 성능이 부족한 것입니다.


네트워크 병목 현상

네 트워크 병목 현상은 네트워크에서 데이터를 송수신하는 서버의 성능에 영향을 미칩니다. 서버의 네트워크 카드에 문제가 있을 수 있거나, 네트워크가 포화 상태여서 분할해야 할 수 있습니다. 다음 카운터를 사용하여 잠재적인 네트워크 병목 현상을 진단할 수 있습니다.
  • Network Interface\Bytes Total/Sec 프 레이밍 문자를 포함하여 각 네트워크 어댑터를 통해 보내고 받는 바이트의 비율을 측정합니다. 인터페이스의 70% 이상이 사용되면 네트워크가 포화 상태입니다. 100Mbps NIC의 경우 사용되는 인터페이스는 8.7MB/초입니다(100Mbps = 100000kbps = 12.5MB/초* 70%). 이와 같이 포화 상태이면 더 빠른 네트워크 카드를 추가하거나 네트워크를 분할해야 할 수 있습니다.
  • Network Interface\Output Queue Length 출력 패킷 큐의 길이(패킷)를 측정합니다. 이 값이 2보다 크면 네트워크가 포화 상태입니다. 이 문제는 더 빠른 네트워크 카드를 추가하거나 네트워크를 분할하여 해결할 수 있습니다.


프로세스 병목 현상

제 대로 작동하지 않는 프로세스나 최적화되지 않은 프로세스가 있으면 서버 성능이 크게 저하될 수 있습니다. 스레드 및 핸들 누수는 결국 서버 다운으로 이어지고, 과도한 프로세서 사용은 서버 속도를 저하시킵니다. 다음 카운터는 프로세스 관련 병목 현상을 진단할 때 유용합니다.
  • Process\Handle Count 프로세스로 현재 열린 총 핸들 수를 측정합니다. 이 값이 10,000보다 크면 핸들 누수 가능성이 있습니다.
  • Process\Thread Count 프로세스에서 현재 활성 스레드 수를 측정합니다. 이 값이 최소 및 최대 스레드 수 사이에서 500보다 크면 스레드 누수 가능성이 있습니다.
  • Process\Private Bytes 다른 프로세스와 공유할 수 없는 이 프로세스에 할당된 메모리의 양입니다. 이 값이 최소 및 최대 스레드 수 사이에서 250보다 크면 메모리 누수 가능성이 있습니다.
2009/07/27 18:47 2009/07/27 18:47

윈도우 2000부터 자체적으로 TELNET 서비스를 제공합니다. 하지만, 보안상의 이유로 이를 활성화 하기는 어렵습니다. remote는 telnet의 1회용으로, 또는 정기 점검과 같은 작업을 위해서 임시로 세션을 열고자 할 때에 사용할 수 있습니다. 이런 명령 프롬프트의 사용을 통해 대규모 서버를 운영할 때 배치 작업을 조금이나마 편하게 진행할 수 있으며, 또한 작업을 확인하기 위한 용도로 사용할 수 있습니다. GUI기반의 환경을 제공하는 윈도우의 특성상 그다지 강력한 기능을 기대할 수는 없지만, 잘 만들어진 cscript나 vbscript, 또는 powershell을 이용한다면 강력한 작업 환경을 지원 받을 수 있습니다.


  1. remote.exe 설치
    1. 윈도우 시디-SUPPORT\TOOLS 로 이동
    2. SUPTOOLS.MSI 설치
    3. remote 파일의 위치 : C:\Program Files\Support Tools
  2. 서버 설정
    사용법 : remote /s cmd sessionname

    예> remote /s cmd serversession

    참고 : hostname이 “dns”로 잡혀 있음

  3. 클라이언트 접속
    사용법 : remote /c SERVERADDRESS sesstionname

    예> remote /c 12.34.56.78 serversession


    접속할 PC의 이름이 “이??PC”지만, remote로 접속 후 “dns”로 변경되었음


  4. Process Explorer로 본 remote 서버 실행
    Process Explorer의 구조를 보면 remote가 cmd를 실행하고 있음

  5. 이후 모든 작업은 클라이언트와 서버 둘 다 같은 화면을 공유하게 되며, GUI기반의 프로그램은 공유가 되지 않습니다.

    출처 : http://www.ntfaq.co.kr/4292

2009/07/27 18:46 2009/07/27 18:46
내컴퓨터 속성에서 advanced 에서 smooth edges of screen fonts,use drop shadows for
icon labels on the desktop , use visual styles on windows and bottons 옵션 빼고 다 체크
헤제 해준다



<익스플로러 기능 활성화>

인터넷 옵션 - security 에서 보안 레벨을 low로 해준다.



<사운드, 테마 기능 활성화>

실행 - services.msc

메뉴중 theme, windows audio 를 automatic으로 설정하고 start 시켜준다.

제어판의 sound / audio device 에서 볼륨을 조정하고

speaker setting의 advanced 탭 - performance 탭에서

하드웨어 가속 full, 퀄리티 best로 해준다.



<DirectX 활성화>

display 설정창 - settings - advanced - troubleshoot 에서 하드웨어 가속을 full로 한다.

실행 - dxdiag

디스플레이 탭의 3D 가속을 enable 한다.



<시스템 설정>

시스템 등록정보 - advanced - performance / advanced 에서 플그램에 우선권을 준다.

시스템 등록정보 - advanced - startup & recovery 에서 메모리덤프를 none으로 설정한다.



<원격지원 활성화>

실행 - gpedit.msc

computer configuration - administrative templates - system - remote assistance

기능을 on 한다.



<종료시 Event Tracker 창 없애기>

실행 - gpedit.msc

computer configuration - administrative templates - system 에서

display shutdown event tracker 를 disable 해준다.



<시작시 ctrl+alt+del 안누르기>

실행 - gpedit.msc

computer configuration - windows setting - security setting - local policies -
security option - interractic logon:do not require ctrl+alt+del 를 활성화한다.

실행 - control userpasswords2 체크 해제하면 로그인시 암호 안물어봄
2009/07/27 18:32 2009/07/27 18:32
윈2003의 미디어 서비스를 이용한 실시간 스트리밍하기
(일명 방송국같은데서 해주는 OnAir서비스)

방식은 미디어인코더에서 특정포트를 이용해서 뿌려주면 미디어서비스에서 이걸 받아 스트리밍해주는겁니다.
결국 미디어서비스없이도 스트리밍은 가능하다는것이지요.
하지만 미디어서비스가 있으면 버퍼링속도가 확실히 차이가 나게 됩니다.


OS : windows 2003 enter sp1 한글판

1. 미디어 서비스 설치
제어판 - 프로그램 추가/제거 - windows 구성요서 추가/제거 - 맨 아래 windows media 서비스 체크 - 다음

2. 미디어 인코더 다운로드 및 설치
http://download.microsoft.com/download/7/a/c/7acbc6a7-7197-4efe-abf7-dbd0d11605e1/WMEncoder.exe
(설치는 하실줄 아시죠?)

3. 미디어 인코더 실행
시작 - 프로그램 - windows media - windows media 인코더

4. 세션 생성하기
처음 실행하면 "새 세션" 이라는 창이 뜨는데 여기서 설정을 하면 됩니다.
혹은 파일 - 새 세션, ctrl + N 으로 표시 할 수 있습니다.
(전 mp3와 사운드카드의 라인인을 연결해서 해보겠습니다)

- 새 세션에서 라이브 이벤트 브로드캐스트 선택후 확인
- 장치옵션에서는 오디오의 사운드 카드를 선택(사운드의 소스를 사운드카드가 받으므로)
(인코딩 보드들 달고 있으면 비디오도 활성화됩니다. 실시간TV를 할 수도 있다는 뜻이지요)
- 브로드캐스트 방법은 "인코더에서 풀"을 선택
- 브로드캐스트 연결에서 포트 아무거나 정하시고 다음
- 인코딩 옵션에서는 어느정도의 음질이나 화질로 쏠것인가를 결정하는겁니다.
(전 라디오를 할 것이므로 다중비트전송률의 135Kbps 선택하겠습니다)
- 쭉쭉 넘어가다 정보표시에 알아서 작성해 넣으세요
- 설정검토 밑의 "[마침]을 클릭하면 브로드캐스트 시작"에 체크하거나 마침을 누른후 컨트롤-인코딩시작을 누르면 됩니다.

*인코딩이 시작되면 인코더의 왼쪽에 볼륨이 표시가 됩니다. 볼륨의 움직임이 없다면 아래쪽의 "믹서"를 눌러 사운드 소스가 제대로 선택되있는지 확인하세요


5. 미디어 서비스 실행
제어판 - 관리도구 - windows media 서비스

6. 게시 지점 추가
미디어 서비스를 실행하게 되면 좌측에 windows media 서비스 - (현재 pc이름) - 게시 지점을 선택합니다.
오른쪽 창의 하단부의 아이콘중 맨 왼쪽것이 게시지점 추가입니다.

- 게시지점 이름(이건 목록에 표시될 이름입니다. 일단 FM이라고 이름짓겠습니다)
- 콘텐트형식(인코더 선택)
- 게시지점 선택(브로드캐스트 게시 지점 밖에 없음)
- 브로드 캐스트 게시 지점 배달 옵션(유니캐스트 선택. 차이점은 검색으로 해결하세요 ^^;)
- 인코더 URL(http://위의 미디어인코더를 실행중인 pc의 아이피:아까정한 포트번호)
- 마법사를 마친후 다음을 수행합니다에서 체크끄기(이건 해도되고 안해도 됩니다. 나중에도 할 수 있구요.)

이러면 끝났습니다.
확인 주소는 "mms://미디어 서비스가 실행중인 pc아이피나 도메인주소/게시지점이름(제가 FM라고 한것)" 입니다.


* asx파일을 만들고 싶으면 미디어서비스의 FM - 알림 - 유니캐스트 알림 마법사 실행를 실행하시면 됩니다. 이건 간단하니 굳이 설명안해도 되겠네요.
asx파일을 만들면 좋은점은 이 파일만 실행하면 되니까 다른사람에게 굳이 주소를 안알려줘도 된다는겁니다.
2009/07/27 18:31 2009/07/27 18:31
1. 클라이언트에서 다음 레지스트리 하위 키로 이동합니다.     HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSLicensing
 
2. MSLicensing을 클릭합니다.
 
3. 레지스트리 메뉴에서 레지스트리 파일 내보내기를 클릭합니다.
 
4. 파일 이름 상자에 mslicensingbackup을 입력한 다음 저장을 클릭합니다.
 
5. 나중에 이 레지스트리 키를 복원해야 할 경우 mslicensingbackup.reg를 두 번 클릭합니다.
 
6. 편집 메뉴에서 삭제를 클릭한 다음 예를 클릭하여 MSLicensing 레지스트리 하위 키 삭제를 확인합니다.
 
7. 레지스트리 편집기를 닫고 컴퓨터를 다시 시작합니다.
 
2009/07/21 11:58 2009/07/21 11:58
보편적인 암호화 알고리즘인 md5를 이용해 mssql 2000 에 저장된 사용자 패스워를 암호화 하고자 합니다.
그런데 2000 에서는 md5가 안되더군요. 그렇다고 db 를 2005 로 바꾸기엔 대형공사라..
여하튼 2000에선 md5가 안된다는걸 여태 몰랐습니다. ㅡㅡ;;
구글 사마의 도움을 받아 겨우 mssql 2000에서 사용할수 있는 md5.dll 화일을 발견했습니다.
혹시 필요하신분들이 있을듯 해서 글을 남겨 둡니다.


mssql 2000
자체적으로 md5를 지원하는 함수가 없다.
그래서 지원하는 dll 화일을 등록한다던지의 방법을 사용해야 한다.
http://www.codeproject.com/KB/database/xp_md5.aspx
에서 관련 dll 화일을 회원가입후 받아볼수가 있다.

등록은 C:\Program Files\Microsoft SQL Server\MSSQL\Binn 과 같은 MSSQL 실행화일 디렉토리에
다운로드한 xp_md5.dll 를 복사한후 아래의 문장을 실행하자

USE master;
EXEC sp_addextendedproc 'xp_md5', 'xp_md5.dll'

그후 사용자 함수로 사용하기 위해
사용할 DB에 아래의 함수를 추가 한다.
CREATE FUNCTION [dbo].[fn_md5] (@data TEXT)
RETURNS CHAR(32) AS
BEGIN
DECLARE @hash CHAR(32)
EXEC master.dbo.xp_md5 @data, -1, @hash OUTPUT
RETURN @hash
END


mssql 2005
자체적으로 md5를 지원한다. 다만 일반적인 프로그래밍에서의 md5 변환값과 동일하게 맞춰주기 위해
소문자처리등의 추가 변환이 필요하다
SubString(master.dbo.fn_varbintohexstr(HashBytes('MD5', 필드명 또는 문자열)), 3, 32)
만약 위에서 언급한 함수를 등록해서 사용하려면 2000과 똑같은 과정을 거치서 스칼라 함수로 등록하면된다.
2009/07/16 19:40 2009/07/16 19:40
update 테이블명 set AAA = ''  where AAA  is null

-AAA는 테이늘 컬럼 열값으로 AAA에 해당하는 열의 <NULL> 값을
  공백값으로 바꾸어 준다
2009/05/16 06:26 2009/05/16 06:26