2010-08-16 2 views
1

'log'라는 테이블이 있다고 가정하면 커다란 레코드가 있습니다.SQL의 로깅 테이블에 대한 적절한 쿼리 및 인덱스

SELECT * 
FROM log 
WHERE logLevel=2 AND (creationData BETWEEN ? AND ?) 

logLevelcreationData 인덱스를 가지고 있지만, 레코드의 수는 데이터를 검색하는 데 시간이 더 걸릴 수 있습니다 :

응용 프로그램은 일반적으로 간단한 SQL에서 데이터를 검색합니다.

어떻게 해결할 수 있습니까? 그들은 테이블이 가지고있는 15의 5 열 목록을 너무 게으른 때문에

+0

이 쿼리에 대해 말해? –

답변

5

실행 계획/"EXPLAIN PLAN"결과 - 많은 양의 데이터를 검색하는 경우 성능을 향상시키기 위해 할 수있는 일은 거의 없습니다. SELECT 문을 변경하여 현재있는 열만 포함 시키십시오. 관심이 있지만 논리적 읽기 횟수가 변경되지 않으므로 성능에 무시할 수있는 영향 만 미칠 것입니다.

적은 수의 레코드 만 검색하는 경우 LogLevel의 인덱스와 CreationDate의 인덱스가 트릭을 수행해야합니다.

업데이트 : SQL 서버는 대용량 데이터베이스의 작은 하위 집합을 쿼리 (예 : 수백만 개의 데이터베이스에서 단일 고객 레코드를 반환)하는 것과 관련이 있습니다. 진정으로 큰 데이터 세트를 반환하기 위해 실제로 준비되지 않았습니다. 당신이 반환되는 데이터의 양이 경우 진정으로 대형은 당신이 할 수있을 것입니다 만 어느 정도가 있고 그래서 물어해야 할 것 :

을 실제로하려고하는 것이 무엇입니까 달성? 당신이 사용자에게 로그 메시지를 표시하는 경우

  • 는, 그들은 한 번에 작은 하위 집합에 관심이있을거야, 그래서 당신은 또한 페이징 SQL 데이터의 효율적인 방법을 조사 할 수 있습니다 - 경우 당신은 단지 500 번 정도의 기록이라 할지라도 여전히 매우 빨라야 만합니다.

  • 통계 분석을 수행하려는 경우 데이터를 통계 분석에보다 적합한 데이터 저장소로 복제 할 수 있습니다. (그러나 그것은 내 전문 분야가 아닙니다.)

+0

질문 뒤에있는 문제는"실제로 달성하려고하는 것이 무엇입니까? "라고 묻는 +1입니다. –

0

의 몇 모든 열을 필요합니까, 사람들은 일반적으로 SELECT *을한다.

하는 RAM을 얻을, 당신은 디스크

에서 읽는 것보다 1000 배 빠른
+0

RAM이 더 있습니까? 캐시 알고리즘을 작성해야한다는 의미입니까? –

+0

더 이상 컴퓨터에 RAM이 없으므로 후속 요청이 디스크에서 데이터를 가져 오는 대신 RAM에 도달합니다. – SQLMenace

+1

더 많은 RAM은 개발자가 영향을 미칠 수있는 선택이 아닌 경우가 많습니다. – AllenG

4

1 캐시에 살 수있는 더 많은 데이터를 themore RAM : 당신의 인덱스가 올바른지, 당신을 확인하십시오 마십시오 Select *
2는 사용하지 통계가 최신입니다.
3 : (선택 사항) 특정 시간이 지난 로그 데이터를보고 있지 않다면 (경험상 1 주일 이상 지난 경우에는 그것을 위해 로그가 필요함) 일부 백업에 보관할 작업을 설정 한 다음 사용되지 않은 레코드를 제거하십시오. 그러면 테이블 크기를 줄여 테이블을 검색하는 데 걸리는 시간을 줄일 수 있습니다.

+0

+1에 대한 제안입니다. 큰 포인트. – Robb

+0

"인덱스가 정확하고 * 통계 *가 최신 상태인지 확인하십시오."라는 약간의 설명을 제안 해 주시겠습니까? 인덱스가 만료 된 경우는 거의 없습니다. :-) – Justin

+0

@AllenG : 바보 같은 질문 : 색인이 최신이 아닌가? 나는 항상 그것이 "자동"이라고 생각했다. –

1

모든 열이 필요합니까?첫 번째 단계는 실제로 검색해야하는 항목 만 선택하는 것입니다.

또 다른 측면은 응용 프로그램에 도착한 후 (데이터 세트 채우기/순차적 읽기 /?) 데이터를 사용한 작업입니다.

처리 응용 프로그램 측면에서 개선 가능성이 있습니다.

당신은 자신에게 이러한 질문에 대답해야합니다

당신이 한 번에 메모리에있는 모든 반환 된 데이터를 보유해야합니까? 검색 측에서 행당 얼마나 많은 메모리를 할당합니까? 한 번에 얼마나 많은 메모리가 필요합니까? 메모리를 재사용 할 수 있습니까?

2

사용중인 SQL 데이터베이스의 종류에 따라 Horizaontal Partitioning을 볼 수 있습니다. 흔히 데이터베이스 측에서이 작업을 완전히 수행 할 수 있으므로 코드를 변경할 필요가 없습니다. 나를 위해

+0

'샤드'는 괜찮을 수 있습니다! –

0

수평 날짜 열

  • 사용 사전 통합의 개념을 기반으로 당신이 할 수있는 두 가지,

    1. 파티션 테이블이 있습니다.

    사전 집계 : 당신은 "로그"표를 할 것이다 preagg에서 "logs_temp"테이블, "logs_summary"테이블과 "logs_archive"테이블. logs 및 logs_temp 테이블의 구조는 동일합니다. 응용 프로그램의 흐름은 이러한 방식으로 모든 로그가 로그 테이블에 기록 된 다음 매 시간마다 다음 작업을 수행하는 cron 작업이 실행됩니다.

    a. 로그 테이블의 데이터를 "logs_temp"테이블에 복사하고 로그 테이블을 비 웁니다. 이것은 암흑 표 트릭을 사용하여 수행 할 수 있습니다.

    b. logs_temp 테이블에서 해당 특정 시간의 로그 집계

    c. 집계 된 결과를 요약 테이블

    d에 저장하십시오. logs_temp 테이블의 레코드를 logs_archive 테이블에 복사 한 다음 logs_temp 테이블을 비 웁니다.

    이렇게하면 결과는 요약 테이블에 사전 집계됩니다.

    결과를 선택할 때마다 요약 테이블에서 결과를 선택합니다.

    이렇게하면 선택 수가 매우 빠릅니다. 왜냐하면 데이터가 시간당 사전 집계 된 것처럼 레코드 수가 훨씬 적기 때문입니다. 한계 값을 1 시간에서 1 시간으로 늘릴 수도 있습니다. 그것은 모두 당신의 필요에 달려 있습니다.

    최근 1 시간 동안 만 데이터를 보유하므로 데이터 양이 많지 않으므로 삽입시 인덱스 재생성 시간이 매우 길어지기 때문에 삽입 시간이 매우 짧습니다. 데이터 세트를 생성하므로 인서트가 빨라집니다.

    당신은

    here 내가 워드 프레스 기반 뉴스 웹 사이트에 사전 집계 방식을 채택 그림자 표 트릭에 대한 자세한 내용을보실 수 있습니다.나는 최근에 인기있는 (지난 3 일 동안 인기있는) 뉴스 아이템을 보여줄 뉴스 웹 사이트 용 플러그인을 개발해야했고, 하루에 100K 히트와 같은 것이 있었고,이 사전 집계는 우리에게 많은 도움이되었습니다. 쿼리 시간은 2 초 이상에서 1 초 미만으로 떨어졌습니다. 플러그인을 공개적으로 곧 제공 할 예정입니다.

  • 0

    다른 답변과 마찬가지로 모든 필드가 실제로 필요하지 않으면 '선택 *'을 사용하지 마십시오.

    있으며 logLevel 및 creationData 인덱스가

    당신은 성능에 영향을 미칩니다을 넣어 어떤 순서로 두 값을 단일 인덱스가 필요,하지만 당신은 가능한 로그 레벨 값의 수가 적은 가정 (그리고 데이터가 비뚤어지지 않는다면) 먼저 creationData를 먼저 추가하는 것이 좋습니다.

    인덱스를 최적화하면 로그 (N)에 대한 쿼리 비용이 줄어들어 레코드 수가 증가하면 여전히 느려질 것입니다.

    C.

    0

    creationData에 의해 당신이 creationDate을 의미하는 것이 정말 바랍니다. 모든

    첫째, logLevelcreationData인덱스를이하는 것만으로는 충분하지 않습니다. 내가 처음 creationData을 넣어

    CREATE INDEX i_log_1 ON log (creationData, logLevel); 
    

    참고 :이 별도의 인덱스가있는 경우, 오라클 만 사용할 수 있습니다 1. 당신이 필요한 것은 두 필드에 단일 인덱스입니다. 이 방법으로 WHERE 절에만 해당 필드를 넣으면 인덱스를 계속 사용할 수 있습니다. (단지 날짜에 대한 필터링은 단순한 로그 수준에서의 시나리오보다 더 가능성이 높습니다.)

    그런 다음 테이블이 데이터로 채워 졌는지 확인하십시오 (프로덕션에서 사용할 데이터만큼). 테이블의 통계를 새로 고치십시오.

    테이블이 큰 경우

    는 (천 백 적어도 몇 행), 통계를 새로 고치려면 다음 코드를 사용 : 테이블이 작은 경우, 사용

    DECLARE 
        l_ownname   VARCHAR2(255) := 'owner'; -- Owner (schema) of table to analyze 
        l_tabname   VARCHAR2(255) := 'log'; -- Table to analyze 
        l_estimate_percent NUMBER(3) := 5; -- Percentage of rows to estimate (NULL means compute) 
    BEGIN 
        dbms_stats.gather_table_stats (
        ownname => l_ownname , 
         tabname => l_tabname, 
         estimate_percent => l_estimate_percent, 
         method_opt => 'FOR ALL INDEXED COLUMNS', 
         cascade => TRUE 
    ); 
    END; 
    

    그렇지 않으면

    ANALYZE TABLE log COMPUTE STATISTICS FOR ALL INDEXED COLUMNS; 
    

    또한 테이블이 커지면 creationDate 열의 범위로 파티션을 분할하는 것이 좋습니다. 자세한 사항은 다음 링크를 참조하십시오 : '계획을 설명하는'무엇을