2013. 7. 30. 15:49

출처 : http://tomcat.apache.org/tomcat-7.0-doc/virtual-hosting-howto.html


renstimpy 라는 두개의 Host-name 을 가진 development-host 가 있다고 가정된 상태에서 진행된다.

톰캣의 한가지 instance가 실행될때 $CATALINA_HOME 는 /usr/local/tomcat/의 경로를 참조한다.


또한 UNIX-Style의 경로 구분 및 명령을 사용하여 수정할 수도 있다.


server.xml


    
    

각각의 호스트의 appBase 아래의 디렉토리 구조가 서로 중복되지 않아야 한다.


webapps 디렉토리


각각의 가상 호스트 디렉토리를 생성한다.

mkdir $CATALINA_HOME/renapps
mkdir $CATALINA_HOME/stimpyapps


Context 구성 - 1


$CATALINA_HOME/renapps/ROOT/META-INF/context.xml


Context 구성 - 2


$CATALINA_HOME/conf/Catalina 와 일치하는 가장 호스트를 만든다.


mkdir $CATALINA_HOME/conf/Catalina/ren
mkdir $CATALINA_HOME/conf/Catalina/stimpy


마지막 디렉토리의 이름이 "Catalina" 속성을 나타낸다.


추가 : 

$CATALINA_HOME/conf/Catalina/ren/ROOT.xml
$CATALINA_HOME/conf/Catalina/stimpy/ROOT.xml


만약 각 호스트에 톰캣의 관리자 web application을 사용하려는 경우에는 

cd $CATALINA_HOME/conf/Catalina
cp localhost/manager.xml ren/
cp localhost/manager.xml stimpy/


부분도 추가해야 한다.

'DBMS' 카테고리의 다른 글

JNDI 톰캣 구성의 예(직역)  (0) 2013.07.30
JDBC Connection Pool  (1) 2013.07.30
Posted by 1+1은?
2013. 7. 30. 15:01

출처 : http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html


데이터 소스를 사용하는 간단한 예 : 

package com.sp.jakarta;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;



public class SimplePOGOExample {

	public static void main(String[] args) throws Exception{
		PoolProperties p =new PoolProperties();
		p.setUrl("jdbc:mysql://localhost:3306/mysql");
		p.setDriverClassName("com.mysql.jdbc.Driver");
		p.setUsername("root");
		p.setPassword("1234");
		p.setJmxEnabled(true);
		p.setTestWhileIdle(false);
		p.setTestOnBorrow(true);
		p.setValidationInterval(30000);
		p.setTimeBetweenEvictionRunsMillis(30000);
		p.setMaxActive(100);
		p.setInitialSize(10);
		p.setMaxWait(10000);
		p.setRemoveAbandonedTimeout(60);
		p.setMinEvictableIdleTimeMillis(30000);
		p.setMaxIdle(10);
		p.setLogAbandoned(true);
		p.setRemoveAbandoned(true);
		p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState" +
							  "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
		DataSource dataSource = new DataSource();
		dataSource.setPoolProperties(p);
		
		Connection conn = null;
		try {
			conn = dataSource.getConnection();
			Statement st = conn.createStatement();
			ResultSet rs = st.executeQuery("select * from user");
			int cnt = 1;
			while (rs.next()){
				System.out.println((cnt++) + ". HOST:" + rs.getString("HOST") + 
						" User:" + rs.getString("User") + " Password:" + rs.getString("Password"));
			}
			rs.close();
			st.close();
		} finally {
			if(conn != null)
				try {
					conn.close();
				} catch (Exception e) {
				}
		}
	}
}

JNDI조회를 위한 resource를 구성하는 방법(<br/> 제외)


          auth="Container"
          type="javax.sql.DataSource"          
          factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
          testWhileIdle="true"
          testOnBorrow="true"
          testOnReturn="false"
          validationQuery="SELECT 1"
          validationInterval="30000"
          timeBetweenEvictionRunsMillis="30000"
          maxActive="100"
          minIdle="10"
          maxWait="10000"
          initialSize="10"
          removeAbandonedTimeout="60"
          removeAbandoned="true"
          logAbandoned="true"
          minEvictableIdleTimeMillis="30000"
          jmxEnabled="true"          
          jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;            
          org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer"
          username="root"
          password="password"
          driverClassName="com.mysql.jdbc.Driver"
          url="jdbc:mysql://localhost:3306/mysql"/>


Asyncronous Connection Retrieval (비동기 연결 검색)


톰캣 JDBC pool connection은 라이브러리에 스레드를 추가하지 않고도 비동기 연결 검색을 지원한다.

이것은 추후의 <Connection> getConnectionAsync() </Connection>을 호출하여 데이터 소스에 메서드를 추가하는 작업을 수행한다.

이러한 비동기 검색을 사용하기 위해서는 두가지 조건이 충족되어야 한다.


fairQueue property를 true로 하고, org.apache.tomcat.jdbc.pool.DataSource 데이터 소스를 캐스팅 해야한다.


비동기 기능을 사용하는 예 : 


Connection con = null;
  try {
    Future future = datasource.getConnectionAsync();
    while (!future.isDone()) {
      System.out.println("Connection is not yet available. Do some background work");
      try {
        Thread.sleep(100); //simulate work
      }catch (InterruptedException x) {
        Thread.currentThread().interrupt();
      }
    }
    con = future.get(); //should return instantly
    Statement st = con.createStatement();
    ResultSet rs = st.executeQuery("select * from user");


'DBMS' 카테고리의 다른 글

Virtual Hosting and Tomcat (가상 호스팅과 톰캣) - (직역)  (0) 2013.07.30
JDBC Connection Pool  (1) 2013.07.30
Posted by 1+1은?
2013. 7. 30. 14:17

MySQL에서 DB에 데이터를 저장하고 리스트로 확인했을때 한글깨지는 현상이 생긴다.


MySQL콘솔로 가서  show variables like 'c%'; 를 실행 하면



C:\Program Files\MySQL\MySQL Server 5.1의 my.ini 를 열어 캐릭터 설정을 바꾼다.


[client]

default-character-set=utf8


[mysql]

default-character-set=utf8


[mysqld]

default-character-set=utf8


바꾼후 (제어판  - 관리도구 - 서비스 - MySQL)로 가서 서버 재가동


이후 아까와 같이 치면 latin1 -> utf-8로 바껴있을 것이다.


그리고 테이블 생성할때 CHARSET=utf8로 해야한다.



create table users(
	num int primary key AUTO_INCREMENT,
    userid VARCHAR(10),
    password VARCHAR(10),
    nickname VARCHAR(10),
    birthday date,
    email VARCHAR(20)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;



이후 데이터를 너보니....



잘나온다...

'DBMS > MySQL' 카테고리의 다른 글

MYSQL 에서 그룹함수(group by)  (0) 2013.07.29
숫자관련 데이타형에 문자형식으로 insert하기  (0) 2013.07.29
Mysql에서의 null값 고찰  (0) 2013.07.29
MYSQL 성능 향상 정리  (0) 2013.07.29
초급QUERY  (0) 2013.07.29
Posted by 1+1은?
2013. 7. 30. 10:33


boardpool.jocl

참고 : http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html

       : http://blog.naver.com/chocolleto?Redirect=Log&logNo=30084743153



1. 커넥션 풀 (Connection Pool)
 
○ 정의

- 데이터베이스와 연결된 커넥션을 미리 만들어 풀(pool)이란 저장소에 저장해 두고 있다가 필요할 때에 커넥션 풀에서 가져다 쓰고
   다시 풀에 반환하는 기법.
- 미리 접속을 하여 메모리에 접속 객체를 저장해 두는 기술.

○ 특징

- pool 속에 미리 커넥션이 생성되어 있기 때문에 커넥션을 생성하는데 드는 연결 시간이 소비되지 않음.
   (어플리케이션의 실행속도가 빨라짐.)
- 커넥션을 계속해서 재사용하기 때문에 생성되는 커넥션 수가 많지 않음.
   (동시 접속자수가 몰려도 웹 어플리케이션이 쉽게 다운되지 않음.)

2. DBCP (Database Connection Pool)

○ 정의

- Database Connection Pool을 구현한 것. (미리 접속을 하여 메모리에 접속 객체를 저장해 두는 기술.)
- Commons DBCP : apache에서 개발한 커넥션 풀 기능을 제공하는 API.

○ 특징
- JDBC의 Connection을 생성하고 사용하지 않는 Connection을 관리하여 Connection의 재사용을 높일 수 있음.

○ 처리 과정

1) DBCP 관련 jar 파일 및 JDBC 드라이버 jar 파일 설치.
2) 커넥션 풀 관련 설정 파일 초기화.
3) 커넥션 풀 관련 드라이버 로딩.
4) 커넥션 풀로부터 커넥션 사용.

○ Web Application에서 DBCP 설정
    
■ 필요한 jar 파일 복사

○ jar 파일

- jakarta commons DBCP
- jakarta commons Collections (Pool이 사용)
- jakarta commons Pool (DBCP가 사용)
(jakarta : http://jakarta-k.sourceforge.net/)      

○ 다운로드

○ 파일 위치

- /WEB-INF/lib 폴더에 위치.

■ 커넥션 풀 설정 파일 작성.
      
○ 특징

- 커넥션 풀에 대한 설정 파일. 
- 파일명 : pool.jocl (파일 이름은 사용자가 지정.)
      
○ 설정 파일 위치

- DBCP API는 클래스패스로부터 설정 파일을 읽어오므로 클래스패스에 위치해 있어야 함.
  (/WEB-INF/classes 폴더 혹은 /build/classes 폴더)

○ boardpool.jocl

 

<object class = "org.apache.commons.dbcp.PoolableConnectionFactory"
    xmlns = "http://apache.org/xml/xmlns/jakarta/commons/jocl">
   
    <!-- mysql 접속. -->
    <object class = "org.apache.commons.dbcp.DriverManagerConnectionFactory">
        <string value = "jdbc:mysql://localhost:3306/board" />
        <string value = "root" />
        <string value = "1111" />
  </object>

  <object class = "org.apache.commons.pool.impl.GenericObjectPool">
    <object class ="org.apache.commons.pool.PoolableObjectFactory" null="true" />
        <int value  =  "10"/>  <!-- maxActive -->
        <byte value = "1"/>  <!-- whenExhaustedAction -->
        <long value = "10000"/>  <!-- maxWait -->
        <int value  = "10"/>  <!-- maxIdle -->     
        <int value  = "3"/>  <!-- minIdle -->     
        <boolean value = "true"/>  <!-- testOnBorrow -->
        <boolean value = "true"/>  <!-- testOnReturn -->
        <long value    = "600000"/>  <!-- timeBetweenEvictionRunsMillis -->
        <int value = "5"/>  <!-- numTestsPerEvictionRun -->
        <long value = "3600000"/>  <!-- minEvictableIdleTimeMillis -->
        <boolean value ="true"/>  <!-- testWhileIdle -->
    </object>

    <object class = "org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory" null="true" />
    <string null = "true" />
    <boolean value = "false" />
     <boolean value = "true" />
</object>


- 주석을 지우고 실행할 것.
- 대소문자 확실히 구분.
        
● GenericObjectPool

- 커넥션 풀의 속성과 관련된 부분.
- API : http://commons.apache.org/pool/api-1.6/index.html
          
□ 속성

속성설명
maxActive커넥션 풀이 제공할 최대 커넥션 개수
whenExhaustedAction커넥션 풀에서 가져올 수 있는 커넥션이 없을 때 어떻게 동작할지를 지정한다. 1일 경우 maxWait 속성에서 지정한 시간만큼 커넥션을 구할 때 까지 기다리며, 0일 경우 에러를 발생시킨다. 2일 경우에는 일시적으로 커넥션을 생성해서 사용한다.
maxWaitwhenExhaustedAction 속성의 값이 1일 때 사용되는 대기 시간. 단위는 1/1000초이며, 0 보다 작을 경우 무한히 대기한다.
maxIdle사용되지 않고 풀에 저장될 수 있는 최대 커넥션 개수. 음수일 경우 제한이 없다.
minIdle사용되지 않고 풀에 저장될 수 있는 최소 커넥션 개수.
testOnBorrowtrue일 경우 커넥션 풀에서 커넥션을 가져올 때 커넥션이 유효한지의 여부를 검사한다.
testOnReturntrue일 경우 커넥션 풀에 커넥션을 반환할 때 커넥션이 유효한지의 여부를 검사한다.
timeBetweenEvctionRunsMillis사용되지 않은 커넥션을 추출하는 쓰레드의 실행 주기를 지정한다. 양수가 아닐 경우 실행되지 않는다. 단위는 1/1000 초이다.
numTestsPerEvictionRun사용되지 않는 커넥션을 몇 개 검사할지 지정한다.
minEvictableIdleTimeMillis사용되지 않는 커넥션을 추출할 때 이 속성에서 지정한 시간 이상 비활성화 상태인 커넥션만 추출한다. 양수가 아닌 경우 비활성화된 시간으로는 풀에서 제거되지 않는다. 시간 단위는 1/1000초이다.
testWhileIdletrue일 경우 비활성화 커넥션을 추출할 때 커넥션이 유효한지의 여부를 검사해서 유효하지 않은 커넥션은 풀에서 제거한다.

 

□ 속성 지정시 고려사항


■ maxActive

- 사이트의 최대 커넥션 사용량을 기준으로 지정.
- 동시 접속자 수에 따라서 지정.
            

■ minIdle
- 사용되지 않는 커넥션의 최소 개수를 0으로 지정하면 풀에 저장된 커넥션의 개수가 0이 될 수 있으며, 이 경우 커넥션이 필요

   할때 다시 커넥션을 생성하게 됨. (최고 개수는 5개 정도로 지정.)
            

■ timeBetweenEvctionRunsMillis
- 이 값을 알맞게 지정해서 사용되지 않는 커넥션을 풀에서 제거하는 것이 좋음.
- 커넥션의 동시 사용량은 보통 새벽에 최저이며, 낮 시간대에 최대.
  (최대 상태에 접어 들었다가 최소 상태로 가게 되면 풀에서 사용되지 않는 커넥션의 개수가 점차 증가.)

- 사용되지 않는 커넥션은 일정 시간 후에 삭제 되도록 하는 것이 좋음. 
  (보통 10 ~20분 단위로 사용되지 않는 커넥션을 검사하도록 지정하는 것이 좋음.)
      

■ testWhileIdle
- 사용되지 않는 커넥션을 검사할 때 유효하지 않은 커넥션은 검사하는 것이 좋음.

■ 드라이버 로드 프로그램 작성
      

○ HttpServlet을 상속받아 초기화.

- 서블릿이 초기에 실행될 때 실행되는 init() 메소드에 작성.
- jsp 페이지에서 DB를 사용하는 부분을 작성할 때 유용. (서버가 실행될 때 한 번만 실행되기 때문에.)
- 자바 파일을 작성한 다음 서블릿 설정파일인 web.xml에 반드시 추가.
        

● 예제


/* DBConInit.java */


package test.connection;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

public class DBConInit extends HttpServlet {
    
    @Override
    public void init(ServletConfig config) throws ServletException {
        
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Class.forName("org.apache.commons.dbcp.PoolingDriver");
            System.out.println("Driver connection success");
        }catch(Exception e) {
            throw new ServletException(e);
        }
        
    }

} 


/* web.xml */

[출처] | commons | DBCP|작성자 외계인셩




    Board
    
        index.html
    

    
        DBConInit
        test.connection.DBConInit
        1 
    

 


/* dbcpTest.jsp */

[출처] | commons | DBCP|작성자 외계인셩


<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>


<%@ page import="java.sql.*"%>

<%
    Connection con = null;

    con = DriverManager.getConnection("jdbc:apache:commons:dbcp:boardpool");
    
    if(con == null) {
        out.print("connection is fail.");
    } else {
        out.print("connection is success");
        con.close();
    }
    
%>


[출처] | commons | DBCP|작성자 외계인셩





 DAO 사용 프로그램 작성



package com.chocolleto.board.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;


/**
 * DB Connection 하는 Singleton class.
 * 
 * @author Administrator
 * 
 */
public class DBUtils {

    private static final String DBCP_POOLING_DRIVER = "org.apache.commons.dbcp.PoolingDriver";
    private static final String MYSQL_JDBC_DRIVER = "com.mysql.jdbc.Driver";
    private static final String JDBC_URI = "jdbc:apache:commons:dbcp:/boardpool";
    
    // 자기 스스로에 대한 인스턴스 생성. (생성자가 private이기 때문.)
    private static volatile DBUtils instance = null;

    private DBUtils() throws Exception {
        try {
            Class.forName(MYSQL_JDBC_DRIVER);
            Class.forName(DBCP_POOLING_DRIVER);
        } catch (Exception e) {
            throw new Exception("Failed to create JDBC drivers.", e);
        }
    }

    public static DBUtils getInstance() throws Exception {
        if (instance == null) {
            // 클래스를 생성하려면 클래스 자체에 대해 접근해야하므로 동기화를 걸어줌.
            synchronized (DBUtils.class) {
                if (instance == null) {
                    instance = new DBUtils();
                }
            }
        }
        return instance;
    }
    
    public Connection getConnection() throws SQLException {
        return DriverManager.getConnection(JDBC_URI);
    }
} 

/* UserDAO.java */

[출처] | commons | DBCP|작성자 외계인셩


package com.chocolleto.board.user;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;

import com.chocolleto.board.db.DBUtils;
import com.chocolleto.board.user.model.User;

/**
 * @author Administrator
 * 
 */
public class UserDAO {
    private DBUtils db;
    // private Logger log = Logger.getLogger(UserDAO.class);
    
    public UserDAO() throws Exception {
        // DB를 관리하는 객체의 인스턴스를 얻어온다.
        db = DBUtils.getInstance();
    }

    /**
     * 사용자 등록
     * 
     * @param user
     * @throws SQLException
     */
    public void insertUser(User user) throws SQLException {

        String sql = "insert into users(userid, password, nickname, birthday, email)"
                + "values(?,?,?,?,?)";

        SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
        String birth;
        if (user.getBirthday() == null) {
            birth = null;
        } else {
            birth = dateformat.format(user.getBirthday());
        }

        Connection con = null;
        try {
            con = db.getConnection();
            PreparedStatement st = con.prepareStatement(sql);

            st.setString(1, user.getUserid());
            st.setString(2, user.getPassword());
            st.setString(3, user.getNickname());
            st.setString(4, birth);
            st.setString(5, user.getEmail());

            st.executeUpdate();
            st.close();
        } catch (SQLException e) {
            throw e;
        } finally {
            if (con != null) {
                try {
                    // 컨넥션은 익셉션이 발생하더라도 항상 close() 될수 있도록 finally 에서 처리한다
                    con.close(); // 실제 컨넥션을 close하는게 아니라 가지고 있던 MySQL의 컨넥션을 풀에 반환.
                } catch (SQLException e) {
                    // 컨넥션을 닫을때 생기는 문제는 무시한다
                }
            }
        }

    }

    /**
     * 사용자 정보 수정
     * 
     * @param user
     * @throws SQLException
     */
    public void updateUser(User user) throws SQLException {

        String sql = "update users set password=?,nickname=?,birthday=?,email=?"
                + " where userid=?";

        SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
        String birth;
        if (user.getBirthday() == null) {
            birth = null;
        } else {
            birth = dateformat.format(user.getBirthday());
        }

        Connection con = null;
        try {
            con = db.getConnection();
            PreparedStatement st = con.prepareStatement(sql);

            st.setString(1, user.getPassword());
            st.setString(2, user.getNickname());
            st.setString(3, birth);
            st.setString(4, user.getEmail());
            st.setString(5, user.getUserid());

            st.executeUpdate();
            st.close();
        } catch (SQLException e) {
            throw e;
        } finally {
            if (con != null) {
                try {
                    // 컨넥션은 익셉션이 발생하더라도 항상 close() 될수 있도록 finally 에서 처리한다
                    con.close();
                } catch (SQLException e) {
                    // 컨넥션을 닫을때 생기는 문제는 무시한다
                }
            }
        }
    }

    /**
     * 사용자 삭제
     * 
     * @param userid
     * @throws SQLException
     */
    public void deleteUser(String userid) throws SQLException {

        String sql = "delete from users where userid=?";
        Connection con = null;
        try {
            con = db.getConnection();
            PreparedStatement st = con.prepareStatement(sql);

            st.setString(1, userid);

            st.executeUpdate();
            st.close();
        } catch (SQLException e) {
            throw e;
        } finally {
            if (con != null) {
                try {
                    // 컨넥션은 익셉션이 발생하더라도 항상 close() 될수 있도록 finally 에서 처리한다
                    con.close();
                } catch (SQLException e) {
                    // 컨넥션을 닫을때 생기는 문제는 무시한다
                }
            }
        }
    }

    /**
     * 사용자 검색.
     * 
     * @param userid
     * @param password
     * @throws SQLException
     */
    public User selectUser(String id) throws SQLException {

        String sql = "select * from users where userid=?";
        Connection con = null;
        User user = null;
        try {
            con = db.getConnection();
            PreparedStatement st = con.prepareStatement(sql);

            st.setString(1, id);

            ResultSet rs = st.executeQuery();

            if (!rs.next()) {
                // 검색된 내용이 없으면 회원이 아니므로 null을 반환.
                rs.close();
                st.close();
            } else {
                // 검색된 내용이 있으면 검색된 내용을 user에 저장.
                user = new User();
                user.setUserid(rs.getString("userid"));
                user.setPassword(rs.getString("password"));
                user.setNickname(rs.getString("nickname"));
                user.setBirthday(rs.getDate("birthday"));
                user.setEmail(rs.getString("email"));
            }

            rs.close();
            st.close();
        } catch (SQLException e) {
            throw e;
        } finally {
            if (con != null) {
                try {
                    // 컨넥션은 익셉션이 발생하더라도 항상 close() 될수 있도록 finally 에서 처리한다
                    con.close();
                } catch (SQLException e) {
                    // 컨넥션을 닫을때 생기는 문제는 무시한다
                }
            }
        }

        return user;
    }
}



'DBMS' 카테고리의 다른 글

Virtual Hosting and Tomcat (가상 호스팅과 톰캣) - (직역)  (0) 2013.07.30
JNDI 톰캣 구성의 예(직역)  (0) 2013.07.30
Posted by 1+1은?
2013. 7. 29. 17:33

출처 : http://www.zetswing.com/bbs/board.php?bo_table=MySQL_LEC&wr_id=40


특정 컬럼으로 그룹핑(group by)을 할때 그룹별 제한하기

 

그룹별 출력 쿼리를 사용할때 조건을 제한 할때는 having을 사용합니다.

having 이라는 예약어를 사용하여 그룹별 제한이 가능합니다.

 


mysql> select code,count(*) from goods group by code;
--code별로 그룹을 짓고 모든 코드와 그룹별코드의 갯수를 출력한다.
mysql> select code,count(*) from goods group by code having count(*) = 1;
--code별로 그룹을 짓고 그룹코드갯수가 1인 코드와 그룹별코드의 갯수를 출력한다.


 

※ having절에는 그룹함수가 옵니다.


'DBMS > MySQL' 카테고리의 다른 글

MySQL 한글깨짐  (0) 2013.07.30
숫자관련 데이타형에 문자형식으로 insert하기  (0) 2013.07.29
Mysql에서의 null값 고찰  (0) 2013.07.29
MYSQL 성능 향상 정리  (0) 2013.07.29
초급QUERY  (0) 2013.07.29
Posted by 1+1은?
2013. 7. 29. 17:32

보통 SQL에서는 데이타를 입력할때 문자관련 데이타형에는 ''을 앞뒤에 붙이고 숫자관련 데이타형에는 ''을 안붙이고 놓습니다.

하지만 mysql에서는 숫자관련 데이타를 입력할때 ''을 붙여도 mysql에서 알아서 입력해줍니다.

''을 붙여서 입력하게되면 예외처리도 처리해줍니다. 아래의 예를 봅시다.

 

mysql> desc leejunsik;
+-------+---------+------+-----+---------+-------+
| Field | Type    | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| a      | int(11)  | YES |      | NULL    |        |
+-------+---------+------+-----+---------+-------+


insert into hong values('13');
--13이 정상적으로 입력됩니다.
 insert into hong values('1A');
--1만 입력됩니다.
 insert into hong values('AA');
--0이 입력됩니다.
 insert into hong values(AA);
--에러가 납니다.
 insert into hong values('');
--0이 입력됩니다.



'DBMS > MySQL' 카테고리의 다른 글

MySQL 한글깨짐  (0) 2013.07.30
MYSQL 에서 그룹함수(group by)  (0) 2013.07.29
Mysql에서의 null값 고찰  (0) 2013.07.29
MYSQL 성능 향상 정리  (0) 2013.07.29
초급QUERY  (0) 2013.07.29
Posted by 1+1은?
2013. 7. 29. 17:31

출처 : http://www.zetswing.com/bbs/board.php?bo_table=MySQL_LEC&wr_id=46


1.null값이란?

 

RDBMS에서 null 은 0이나 공백이 아닌 값을 알수가 없다입니다. 이말은 값이 없다 입니다.

이는 Mysql상에서 문자열을 합치거나 수치를 계산할때 문제가 됩니다. 특히 수치계산일때는 not null로 하거나 defailt 옵션을 주어야 합니다.

 

2.null값의 잘못된 처리

 

수치의 경우

cretae table lee(

a int null,

b int null);

insert into lee values(null,12);

select a+b from lee;

라고 한다면 12가 나올것 같지만 null값이 포함된 계산식은 무조건 null이 나옵니다.

그래서 defailt 문을 써주는게 좋거나 not null을 사용하는게 좋습니다.

 

문자열의 경우

cretae table lee(

a varchar(10) null,

b varchar(10) null);

insert into lee values(null,'lee');

select concat(a,b) from lee;

라고 한다면  nulllee나 lee가 나올것 같지만 결과는 null로 나온다.

 

3.많은 양의 null처리

 

상당히 많은 양의 레코드에 null이 있다면 계산하거나 문자열을 연결하는데 문제가 많다.

update table_name set num=0 where num is null;

update table_name set num='' where num is null;

와같이 null값을 지정된 문자나 숫자로 바꾸어준다.

 

※ table을 만들시에 모든컬럼에 not null을 주는게 좋습니다.

'DBMS > MySQL' 카테고리의 다른 글

MYSQL 에서 그룹함수(group by)  (0) 2013.07.29
숫자관련 데이타형에 문자형식으로 insert하기  (0) 2013.07.29
MYSQL 성능 향상 정리  (0) 2013.07.29
초급QUERY  (0) 2013.07.29
JOIN(조인) 사용하기  (0) 2013.07.29
Posted by 1+1은?
2013. 7. 29. 17:29

출처 : http://www.zetswing.com/bbs/board.php?bo_table=MySQL_LEC&wr_id=47


1.TABLE 관련

 

OPTIMIZE TABLE

table type이 myisam이나 bdb에서 사용하며 많은양의 데이터가 삭제되었거나 삽입되었을때 사용하면 속도향상에 좋습니다.

ex)optimaze table table_name;

 

2.QUERY 관련

 

JOIN

join이 subquery보다 빠르다.
join시 사용되는 컬럼은 동일한 column type과 길이를 가져야만 최적의 속도를 보장한다.

 

index설정

인덱스를 적절히 잡아줍니다.

 

필요한 컬럼만 select 한다.

select * 되어 있는부분을 필요할 필드만 가져옵니다.

 

processlist로 실행 쿼리를 mysql상태를 체크

cd /usr/local/mysql
./bin/mysqladmin -i3 processlist -ppassword

//3초에 한번씩 실행됩니다.

 

잘못된 query 발견

explain으로 질의과정 점검 몇번의 레코드를 검색하여 수행하는지 그리고 해당 컬럼이 index를 잘타는지 보고 쿼리를 수정합니다.

 

slow query log기능

 slow query log를 걸어놓고 slow query time를 한 5초로 정해주시면 5초 이상 실행이 걸리는 쿼리는 모조리 로그에 남습니다.
그 query를 튜닝합니다.(explain이용)

 

query우선 설정

select 구문에는 
select HIGH_PRIORITY id,name, ... from table_name ...

delete, insert, update 구문에는
delete LOW_PRIORITY from table_name ....

 

mysql 4.x 이상부터 지원! 

query cache을 사용합니다.

 

int형과char형의 검색속도차이

int 가 char보다는 검색속도가 더 빠르다고 하지만 시스템구성과 환경마다 다릅니다.

 

3.하드웨어 관련

 

웹호스팅이 아닌 서버호스팅을 합니다.

 

평균 조회 레코드 50만건이상

조회 데이타가 50만건~100만건이면 DB서버와 웹서버를(이미지 서버등등) 나누어 분산처리(2-Tier)하며 조회 건수가 100만건 이상은 ORACLE같은 상용 DB로 교체해야 한다.

 

메모리를 증설 합니다.

1-2G 정도

 

하드디스크 스카시로 교체

e-ide보다 데이타 io(입/출력) 더 빠르다.(10000 rpm이상급)

'DBMS > MySQL' 카테고리의 다른 글

숫자관련 데이타형에 문자형식으로 insert하기  (0) 2013.07.29
Mysql에서의 null값 고찰  (0) 2013.07.29
초급QUERY  (0) 2013.07.29
JOIN(조인) 사용하기  (0) 2013.07.29
4.0 추가기능  (0) 2013.07.29
Posted by 1+1은?
2013. 7. 29. 17:23

출처 : http://www.zetswing.com/bbs/board.php?bo_table=MySQL_LEC&wr_id=50


select * from goods where name like replace(name,' ','') like '%$name%';
(goods table에서 name필드의 공백을 제거하고 변수와 like 비교검색)
 
select count(*) from goods where left(signdate,10) = curdate()
(goods table에서 signdate(data타입)의 좌측의 10개문자만 가져와서 오늘 날짜와 비교)
 
select * from goods where from_unixtime(orderdate) between '2003-01-01' and '2004-01-01';
(goods table에서 timestamp형인 날짜형을 실제 날짜와 비교시  from_unixtime()함수로변환해사용)
 
select SUM(if(paymethod='bank',round(payM/exchange),payM)) from trade;
(trade테이블에서 paymethod컬럼의 값이 bank이면 round(payM/exchange) 의값들을 아니면 payM의 값들의 합을 출력합니다.)
 
select g.name,count(tg.idx) from goods as g,trade_goods as tg where g.idx=tg.goodsIdx  group by g.idx order by 2 desc;
(goods와 trade_goods을 조인하여 trade_goods 테이블에서 판매된 상품의 idx별로 그룹지어 2번째 출력컬럼인 count(tg.idx)의 오름차순으로 출력합니다.)
 
select code,count(code) from goods group by code having count(code)>1
(goods table에서 code 별로 그룹지어 count(code)의 갯수가 2개 이상인것만 출력합니다.)
 
select name,count(tradecode) from trade_goods where tradecode='$tradecode' group by tradecode having count(tradecode)>1;
(tradecode table에서 $tradecode변수와 tradecode컬럼이 같은 레코드에서 tradecode별로 정렬하고 그룹별갯수가 1개 이상인것만 출력한다.)-(주문서 중복 확인 쿼리)


'DBMS > MySQL' 카테고리의 다른 글

Mysql에서의 null값 고찰  (0) 2013.07.29
MYSQL 성능 향상 정리  (0) 2013.07.29
JOIN(조인) 사용하기  (0) 2013.07.29
4.0 추가기능  (0) 2013.07.29
[MySQL] 자동증가값  (0) 2013.07.29
Posted by 1+1은?
2013. 7. 29. 17:18

INNER JOIN (교집합)

 

INNER JOIN(NORMAL JOIN)은 여러 테이블의 조건들이 모두 만족했을때만 데이타를 보여주게 되며 한쪽 테이블의 조건이라도 만족하지 않으면 데이타를
보여주지 않습니다.

 

LEFT OUTER JOIN (교집합)

 

LEFT OUTER JOIN(교집합)은 여러 테이블의 조건들이 모두 만족하지 않더라도 데이타를 보여줍니다.

 

※ 조건이 만족하지 않는 테이블의 데이타값은 "NULL" 값으로 출력된다.

 

간단한 조인 예제

 

개요

 

출석 테이블을 만든다 가정하면 normal join 으로는, 한번도 출석하지 않은 학생은 목록에도 보이지 않게 되지만, outer join 으로는 모두 볼 수 있게 됩니다.

 

예제

 

[테이블 생성]

 

drop table book;
create table book
(
code varchar(10),
name varchar(10)
);
insert into book values ('1111','사랑책');
insert into book values ('2222','이별책');
insert into book values ('3333','웃긴책');

 

drop table animal;

create table animal
(
code varchar(10),
name varchar(10)
);
insert into animal values ('1111','사자');
insert into animal values ('2222','호랑이');
insert into animal values ('3333','오리');

 

drop table buy;
create table buy
(
book_code varchar(10),
animal_code varchar(10)
);
insert into buy values ('1111','1111');
insert into buy values ('2222','2222');
insert into buy values ('3333','4444');

 

[LEFT OUTER JOIN 예제]

 

select
 b.name, c.name
from
 buy as a
 left outer join book as b on a.book_code = b.code
 left outer join animal as c on a.animal_code = c.code;

 

※ left outer join 시에는 최대한 중복건이 안나오도록 유일한 컬럼으로 비교해야 한다.

※ left outer join 시에 조건에 만족하지 않는 테이블의 컬럼값은 "NULL" 로 표기된다.

 

[INNER JOIN 방법1]

 

select 
 b.name, c.name
from
 buy as a
 inner join book as b on a.book_code = b.code
 inner join animal as c on a.animal_code = c.code;

 

[INNER JOIN 방법2]

 

select 
 b.name, c.name
from
 buy as a, book as b, animal as c
where
 a.book_code = b.code and a.animal_code = c.code where a.code = '1111';

select 
 b.name, c.name
from
 buy as a, book as b, animal as c where a.book_code = '1111';

 

여러 테이블 컬럼의 모든 경우의 수를 출력한다.

 

select * from book, animal, buy;

select * from book a, animal b, buy c;

 

-- 3개테이블 컬럼의 경우의 수를 모두 출력한다.

-- 모든 경우의 수 = 각테이블의 로우스를 곱한값

 

RDBMS에서 JOIN은 중요한개념입니다.

서로 관련된 정보 중 정보의 관계가 1:N으로 설계하게 되면 서로 분리하여 2개의 테이블로 분리시킵니다. 여러개로 나누면서 서로 연결할수있는 공통 컬럼을 만들어두면 여러모로 좋은점이

많습니다. 그렇다고 table하나로 해결하는것이 효율적이지 않다는것은 아니지만 각각의 장단점이

있습니다.

 

table category

create table category(

num int not null primary key auto_increment,

name varchar(20) not null)

insert into category values(null,'컴퓨터');

insert into category values(null,'가전제품');

insert into category values(null,'통신기기');

 

table s_category

create table s_category(

num int not null primary key auto_increment,

cate_num int not null,

name varchar(20) not null)

insert into s_category values(null,1,'cpu');

insert into s_category values(null,2,'냉장고');

insert into s_category values(null,3,'pcs');

 

category 와 s_category테이블을 통해 어떤 대분류에 속한 소분류가 있는지 알아보자

ex)select * from category ,s_category where category.num=s_category.cate_num;

만약에 where절을 주지 않게 되면 table category와 table s_category를 곱한 값이

나오게 됩니다.

category의 첫번째 레코드를 가져온후 s_category의 첫번째레코드를 가져와 조건이 맞으면 출력

category의 첫번째 레코드를 가져온후 s_category의 두번째레코드를 가져와 조건이 맞으면 출력

category의 첫번째 레코드를 가져온후 s_category의 세번째레코드를 가져와 조건이 맞으면 출력

 

category의 두번째 레코드를 가져온후 s_category의 첫번째레코드를 가져와 조건이 맞으면 출력

category의 두번째 레코드를 가져온후 s_category의 두번째레코드를 가져와 조건이 맞으면 출력

category의 두번째 레코드를 가져온후 s_category의 세번째레코드를 가져와 조건이 맞으면 출력

..........

 

where 조건이 없으므로 위의 순서대로 모두 출력이 되는것이다.

 

또한 컴퓨터 카테고리에 속한 소분류만을 보고싶다면 다음과 같이 조인하면 된다.

ex)select a.num,a.name,b.num,b.name from category a,s_category b

where a.num=b.cate_num and a.num=1;


'DBMS > MySQL' 카테고리의 다른 글

MYSQL 성능 향상 정리  (0) 2013.07.29
초급QUERY  (0) 2013.07.29
4.0 추가기능  (0) 2013.07.29
[MySQL] 자동증가값  (0) 2013.07.29
Mysql insert 와 select 같이 쓰기  (0) 2013.07.29
Posted by 1+1은?