2009-07-11 6 views
1

캘린더 webapp를 만들고 있는데 이벤트 테이블 생성 및 후속 쿼리에서 성능과 스토리지 문제가 다소 달라 붙어 있습니다. 개념은 "반복되는 이벤트 (매일/매주)로 테이블을 만드는 방법"입니다. 나는 또한 많은 다른 것들을 사용할 수 있습니다 0에서 62까지 숫자의 매우 작은 테이블을 가지고 있지만 이벤트를 보는 쿼리에 MySQL 데이터베이스에서의 쿼리 성능

CREATE TABLE `events` (
    `eventid` int(10) NOT NULL AUTO_INCREMENT, //primary key 
    `evttitle` varchar(255) NOT NULL,    //title of event 
    `createdby` char(8) NOT NULL,     //user identification (I'm using 
    `evtdatestart` date NOT NULL,     ////another's login system) 
    `evtdateend` date NOT NULL, 
    `evttimestart` time NOT NULL, 
    `evttimeend` time NOT NULL, 
    `evtrepdaily` tinyint(1) NOT NULL DEFAULT 0, //if both are '0' then its 
    `evtrepweekly` tinyint(1) NOT NULL DEFAULT 0, //a one time event 
    `evtrepsun` tinyint(1) NOT NULL DEFAULT 0, 
    `evtrepmon` tinyint(1) NOT NULL DEFAULT 0, 
    `evtreptue` tinyint(1) NOT NULL DEFAULT 0, 
    `evtrepwed` tinyint(1) NOT NULL DEFAULT 0, 
    `evtrepthu` tinyint(1) NOT NULL DEFAULT 0, 
    `evtrepfri` tinyint(1) NOT NULL DEFAULT 0, 
    `evtrepsat` tinyint(1) NOT NULL DEFAULT 0, 
    PRIMARY KEY (`eventid`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

, 그것은으로 MOD(num,7)를 통해 사용됩니다 여기에 내 현재의 솔루션입니다 요일. 여기에 해당 쿼리입니다 : 나는 결과를 생성하는 순수한 SQL 방법은 주로하기 때문에이 방법을 좋아

SELECT date, evttitle, evttimestart, evttimeend 
FROM (     //create result of all days between the span of two dates 
    SELECT DATE_ADD(startdate, INTERVAL (num-startday) DAY) AS date, 
    IF(MOD(num,7)=0,7,MOD(num,7)) AS weekday      //1=sun...7=sat 
    FROM (
    SELECT '@startdate' AS startdate, DAYOFWEEK('@startdate') AS startday, 
     '@enddate' AS enddate, DATEDIFF('@enddate','@startdate') AS diff 
) AS span, numbers           //numbers is 0-62 
    WHERE num>=startday AND num<=startday+diff 
) AS daysinspan, events 
WHERE evtdatestart<=date AND evtdateend>=date AND (
    (evtdatestart=evtdateend) OR  //single event 
    (evtrepdaily) OR     //daily event 
    (evtrepweekly AND (    //weekly event 
    (weekday=1 AND evtrepsun) OR ////on Sunday 
    (weekday=2 AND evtrepmon) OR ////on Monday 
    (weekday=3 AND evtreptue) OR ////on Tuesday 
    (weekday=3 AND evtrepwed) OR ////on Wednesday 
    (weekday=3 AND evtrepthu) OR ////on Thursday 
    (weekday=3 AND evtrepfri) OR ////on Friday 
    (weekday=3 AND evtrepsat)  ////on Saturday 
))  //end of repeat truths 
) 
ORDER BY date, evtstarttime; 

, 그것은 반복되는 일정 경우 50 개 이상의 시간을 복제하는 데에서 저를 저장하고, 그것이 쉽게 반복 이벤트를 수정합니다. 그러나 사용자가 수행하는 가장 일반적인 쿼리 일 가능성이 있으므로 성능이 느려지는 것은 용납되지 않습니다.

또 다른 방법은 evtrep 열을 포함시키지 않고 범위에 필요한만큼 새로운 이벤트를 재생성하는 것입니다. 그러나 나는이 아이디어를 복제함으로써 많은 데이터가 나를 싫어하는 것처럼 생각하지 않습니다. 그러나, 내가보기에 훨씬 더 빠른 결과를 얻을 수 있다면 (그리고 룩업 쿼리가 훨씬 쉽고 빠를 것임), 그러면 여분의 스토리지를 정당화 할 수있을 것입니다.

여러분 모두 더 나은 계획이라고 생각하는 사람이 있습니까? 아니면 내가 여기에서 언급하지 않았거나 언급하지 않은 또 다른 것이 있습니까?

미리 감사드립니다.

업데이트 1 : 사람 - b는 좋은 제안을했습니다. 나는 그 사람 - b가 제 표가 제 1의 정상적인 형식이 아닐 수도 있다고 생각합니다. 많은 경우 (~ 30 % 이상)의 사건이 반복되지 않는다고 가정합니다. (제 경우에는 80 % + 이벤트는 반복 이벤트 일 수 있습니다). 그러나, 내 질문에 대한 그의 첫 번째 업데이 트에, 사람 - b의 변경 제안 또는 reptimes을 추가하는 것만으로 인해 (내 경우에는 PHP입니다) 백 엔드에 날짜 처리를 푸시 할 것이라고 생각합니다. 나는 아직도 설명해야한다. 하지만 내 주요 관심사 (질문)는 다음과 같습니다. 수동으로 반복 이벤트에 대한 항목 수를 수동으로 생성하지 않고 모든 이벤트의 날짜와 시간을 계산할 수있는 쿼리 기반 당 평균 속도가 가장 빠른 방법은 무엇입니까?

답변

1

테이블을 표준화 해보십시오. (여러 개의) 날짜 및 반복 정보와 이벤트 정보를 분리하십시오.

업데이트는 :

SELECT e.evttitle, r.reptimes FROM events e, repeats r WHERE e.eventid = 9 
이 같은 쿼리 (안된)를 사용, 그리고

CREATE TABLE `repeats` (
    `repweek` tinyint(1) NOT NULL DEFAULT 0, // if 0, don't repeat, otherwise, the day 1..7 of the week 
    `repday` tinyint(1) NOT NULL DEFAULT 0, // repeat daily if 1 
    `reptimes` int(10) NOT NULL DEFAULT 0, // 0 for indefinite, otherwise number of times 
) 

:
표 1 :

CREATE TABLE `events` (
    `eventid` int(10) NOT NULL AUTO_INCREMENT, //primary key 
    `repeatid` int(10) NOT NULL, 
    `evttitle` varchar(255) NOT NULL,    //title of event 
    `createdby` char(8) NOT NULL,     //user identification (I'm using 
    `evtdatestart` date NOT NULL,     ////another's login system) 
    `evtdateend` date NOT NULL, 
    `evttimestart` time NOT NULL, 
    `evttimeend` time NOT NULL, 
    PRIMARY KEY (`eventid`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

표 2 다음은 예입니다

추가 정보 (bot 동일한 가이드의 h)는 Simple joinsNormalisation에 있습니다.

이렇게하면 시스템이보다 유연 해지고 더 빨라집니다.

+0

이전 메모를 삭제 한대로 삭제했습니다. 내 업데이트를 참조하십시오.내 원래의 질문에 자신을 잘 진술하지 않았을 수도 있습니다. – Mike

+0

그럴 경우 확실하지 않습니다. :(나는 이것을 여기서 지킬 것이다. –