2010-07-20 4 views
1

나는 과거 기간, 지난 주 및 지난 달의 세 기간에 걸쳐 클릭 수를 추적합니다. 열은 계산 열이 합세 개의 테이블을 하나의 열 또는 너무 많은 열로 결합 하시겠습니까?

  • 에게 제공과 함께, 두 개의 다른 속성 및 hour_24에 hour_1을 LINK_ID으로,

    • 시간별 테이블 :

      이 작업을 수행하기 위해, 나는 세 개의 테이블을 가지고 합계를 계산하는 열과 함께 click_id 열, 다른 두 개의 특성 및 day_1부터 day_7까지의 계산식 열

    • 위와 같이 day_1부터 day_31까지의 열이있는 테이블

    클릭이 오면 다른 표에 href, description 등의 주요 속성을 저장하고 위의 표에서 각각의 link_id에 해당하는 행을 삽입 또는 업데이트합니다.

    각 링크는 위의 시간별/요일/월별 표에 사용자가 앉아있는 위치와 같은 다른 두 속성에 따라 여러 항목을 가질 수 있습니다.

    사용자가 유형 A이고 X에 앉으면 위의 표에 3 개의 행이 생성되거나 추가됩니다. 첫 번째 행은 해당 기간 동안 해당 링크의 모든 클릭을 기록하고 두 번째 행은 모든 클릭을 기록합니다. '유형 A', 세 번째 '모든 사용자의 클릭 수'.

    각 시간/일/주/월 주위로 데이터를 이동하지 않으려 고했기 때문에이 방법으로 설계했습니다. 난 그냥 "현재 시간"(1-24), "현재 하루"(1-31) 및 "현재 평일"(1-7)에 대한 포인터를 유지하고 테이블의 해당 셀에 쓰기. 새로운 기간 (예 : "오후 3시 - 오후 4시")을 입력하면 현재 열 (예 : hour_15)을 비워두고 링크가 들어올 때마다 해당 열을 증가시키기 시작할 수 있습니다. 모든 빈번히 나는 오래된 행을 삭제할 수 있습니다 "모두 제로"로 낮추십시오.

    이렇게하면 열 데이터를 이동할 필요가 없습니다. 열 데이터가 잠재적으로 수십만 개가 될 가능성이 매우 높습니다.

    삽입/업데이트 이전의 현재 요일/요일/시간 행 또는 속성을 기반으로 계산 된 열의 TOP 20 값만을 선택합니다 (이러한 결과를 1 시간 정도 캐시 할 가능성이 높습니다)).

    테이블이 채워지면 UPDATES는 많은 고유 한 href가 없으므로 INSERT를 훨씬 초과합니다.

    세 가지 질문 :

    • 이 monthdays/평일/시간의 하나 개의 큰 테이블에 세 개의 큰 테이블을 결합 할 OK인가? 이것은 64 컬럼을 가진 테이블을 제공 할 것인데, 나는 과잉이라고 확신하지 못한다. 다른 한편으로, INSERT/UPDATE 문을 세배로하는 것과 같이 별도로 유지하는 것이 필요합니다. 나는 SQL Server에 대해 어느 것이 최선인지 알기에는 충분하지 않습니다.

    • 이 방법이 의미가 있습니까? 물론 작업 한 대부분의 데이터 세트는 항목 당 별도의 행을 가지며 날짜순으로 정렬됩니다.하지만 수천 명의 사용자가 클릭 수를 추적하면 많은 수십만 개의 행을 가져올 수 있습니다. 매우 자주 주문하고 합산하는 것은 끔찍할 것입니다. 추적기가 입증되면 클릭 수를 수백 페이지 이상으로 끌어 올 계획이 있으므로 확장해야합니다.

    • 디자인 측면에서 볼 때, 평일과 월 모두가 중복되어 있음이 분명합니다. 그러나 이것이 내가 열을 가리키는 포인터를 유지하고 빠르게 업데이트하고 계산 된 열을 사용하는 유일한 방법이었습니다. 평일 테이블을 삭제하면 이전 7 일을 합산 한 '월간'에 대한 추가 계산 열이 필요합니다 (예 : 오늘이 21 일, sum day_14, day_15, day_16 ... day_20). 계산은 매일 업데이트해야하는데 비용이 많이들 것이라고 상상합니다. 따라서 간단한 정적 계산을위한 추가 "평일"테이블. 소규모 데이터 스토리지보다 간단하고 빠른 계산을 중요하게 생각합니다.

    미리 감사드립니다.

  • 답변

    4

    column_1, column_2, column_3과 같이 이름에 숫자가있는 열을 볼 때마다 ... '끔찍한 데이터베이스 디자인'플래그가 발생해야합니다. (FYI, 여기서 1NF를 위반하고 있습니다. 구체적으로 당신은 repeating groups across columns입니다.

    이제는 이러한 구현이 생산에 받아 들여질 수도 있고 (또는 심지어 필요할 수도 있음) 개념적으로 틀림없이 틀 렸습니다.

    Geert가 말한 것처럼 개념적으로 두 개의 테이블로 충분합니다. 성능이 문제가되는 경우는 주간/월간 통계 데이터를 비정규 수 있지만, 여전히 나는 위로를 모델링하지 않을 그러나 나는 계속 것

    CREATE TABLE base_stats (link_id INT, click_time DATETIME) 
    CREATE TABLE daily_stats (link_id INT, period DATETIME, clicks INT) 
    

    할 수 있습니다 항상 집계

    SELECT link_id, count(*) as clicks, DATE(click_time) as day 
    FROM base_stats 
    GROUP_BY link_id, day 
    

    에있는 daily_stats를 채우기 위해 주기적으로 실행할 수 있습니다. 최신 상태로 유지하려면 트리거에서 구현할 수 있습니다 (또는 꼭 필요한 경우 응용 프로그램에서 수행하십시오). 필요한 경우 다른 레벨의 데이터를 비정규화할 수도 있습니다 (더 많은 집계 테이블을 만들거나 집계 된 데이터 테이블에 다른 열을 추가 함). 그러나 너무 조숙 한 최적화 일 수 있습니다.

    위의 디자인은 향후 애드혹 분석을 위해 훨씬 더 깨끗합니다 (통계와 함께 발생). 다른 혜택을 보려면 반복 그룹에서 위키 백과를 참조하십시오.

    편집 : 두 테이블 base_statsaggregated_stats과 솔루션은 다음과 같은 전략을 수락하더라도 :

    • 주기적으로 daily_statsbase_stats에서 데이터를 집계 base_stats
    • 의 각 클릭을 삽입하고 전체를 제거 세부 정보

    최적의 솔루션이 아닐 수 있습니다. 요구 사항에 대한 토론 및 설명을 토대로 테이블 base_stats이 필요하지 않은 것으로 보입니다. 다음과 같은 접근 방식은 조사해야합니다

    CREATE TABLE period_stats (link_id INT, period DATETIME, ...) 
    

    업데이트

    UPDATE period_stats 
    SET clicks = clicks + 1 
    WHERE period = @dateTime AND link_id = @url AND ... 
    

    이 테이블을 갱신 비용은 제대로 인덱스는 base_table에 행을 삽입 한 효율적이고 어떤이는 쉽게로 쉽게 분석을 위해 사용하는 것

    SELECT link_id, SUM(clicks) 
    FROM period_stats 
    WHERE period between @dateTime1 AND @dateTime2 
    GROUP BY ... 
    
    +0

    감사합니다. 예, 이것이 내가 시작한 것입니다. 아주 많이 제기 된 깃발, 따라서이 게시물. 나는 데이터에 대해 너무 많은 분석을하기를 원하지는 않지만 더 개방적 일수록 더 좋다. 핵심은 성능입니다. 이것은 인트라넷의 동적 탐색 모델을 향한 첫 번째 단계입니다. 사용자는 엄격한 계층 구조에 의존하기보다 "동료와 가장 인기있는", "이번 주 가장 인기가있는"등으로 찾아 볼 수 있습니다. 큰 변화 .... – Jhong

    +0

    ... 클릭 수신기는 페이지의 대부분의 링크에 연결되며 10k 사용자의 경우 엄청난 양의 데이터가 유입됩니다. 이렇게하면 응용 프로그램 서버가 크롤링 속도가 느려집니다 나는 이것이 미래라고 사람들에게 납득시키는 데 어려움을 겪을 것입니다. 한편, 이것이 우리 홈페이지에서 입증되면, 인트라넷의 대부분의 모든 페이지 (Sharepoint 인스턴스를 포함하여 수천 페이지)와 더 많은 사용자를위한 방법으로 추진할 것입니다. 정확한 분석에 관심이 없습니다.이 단계에서 순수하게 집계됩니다. ... – Jhong

    +0

    ... 나는 정규화 된 모델을 선호하지만 50 만 개의 행이있는 테이블에서 그룹 및 순서와 함께 count (*)가 얼마나 비쌉니까? 테스트를 대신하는 것은 없지만, 나는 올바른 볼 파크에서 디자인을 얻고 싶어합니다. – Jhong

    3

    데이터베이스에서 수행 한 비정규 화는 일부 문제의 경우 좋은 해결책이 될 수 있습니다. 당신의 경우에는 그러나 나는 당신이 미래에 필요할지도 모르는 정보를 잃어 버렸기 때문에 주로 위의 해결책을 선택하지 않을 것입니다, 아마도 당신은 앞으로 30 분 간격으로보고하기를 원할 것입니다. 그래서 설명을 보면 링크 (ahref와 설명)와 링크 (클릭 한 날짜와 시간 및 어쩌면 다른 데이터 포함)에 대한 클릭 만 2 개의 테이블로 할 수 있습니다. 물론 단점은 수천 개의 레코드로 구성된 hunderds를 저장해야하며이 양의 데이터를 쿼리하는 데 많은 시간이 걸릴 수 있다는 것입니다. 이 경우이 두 테이블에 집계 데이터를 별도의 테이블에 저장하고 이러한 테이블을 정기적으로 업데이트하는 것이 좋습니다.

    2

    그 디자인은 정말 나쁩니다. 비합리적인 제안이 더 좋습니다. 당신이 좋은 쉽게 확인하려면
    , 당신은뿐만 아니라이 개 분야에 하나의 테이블을 할 수 :

    timeSlice 
        clickCount 
        location 
        userType 
    

    를 타임 슬라이스가 시간 반올림 날짜와 시간을 들고. 나머지는 모두 공제 할 수 있으며
    24 * 365 * locations # * types #
    /년입니다.

    항상이 테이블 디자인을 사용하면 구성 및 실행 가능성에 따라 결국 값을 메모리에 누적하여 10 초당 한 번만 테이블을 업데이트 할 수 있습니다. 또는 임의의 시간 길이 < = 허용 위험에 따라 1 시간

    +0

    예, 그러나 나는 클릭 테이블에 스트리밍되는 50 만 건의 클릭에 대해 걱정했습니다. 그렇다면 클릭을 맹목적으로 삽입하는 것이 현재 카운트를 선택하고 열을 증가시켜야하는 현재 방법보다 훨씬 저렴하다고 생각합니다. 엄청난 결과 세트를 선택하고 계산하는 것은 킬러가 될 것이지만 캐시 할 수 있습니다. – Jhong

    +0

    클릭 스트리밍 : 적어도 (1) ​​레코드를 쉽게 찾을 수 있습니다. (2) 기술적으로 가능하면 테이블을 증가시키기 전에 10 번의 클릭을 기다리는 것이 좋습니다. 그리고 (3) 어쨌든 클릭이 스트리밍됩니다. 3을 곱합니다. –

    +0

    링크 수와 동료 수, 동료 수, 다른 수를 곱해서 연간 24 * 365 개의 레코드가 생성됩니다. 링크가 이미 10,000으로 추정되므로 수백만 건의 레코드를 쉽게 실행할 수 있습니다. 적절한 인덱스가 있으면 OK 일 수 있습니다. 테스트는 갈 길이 멀다. – Unreason

    관련 문제