2009-07-11 3 views
1

Я создаю календарь webapp, и я как бы застрял между проблемой производительности и хранилища при создании и последующих запросах моей таблицы событий. Понятие «как сделать таблицу с повторяющимися событиями (ежедневно/еженедельно)?» Вот мое текущее решение:Производительность запросов 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; 

У меня также есть очень небольшая таблица чисел от 0 до 62, которые могут быть использованы для различных вещей, но в запросе отрываясь событиями, она используется с помощью MOD(num,7), как день недели. Вот этот запрос:

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; 

Мне нравится этот способ в основном потому, что это чистый SQL способ генерации результатов, это избавляет меня от необходимости дублировать событие 50+ раз для повторяющихся событий, и это делает его более легким для изменения повторяющихся событий. Однако неприемлемо, чтобы производительность была медленной, поскольку это, скорее всего, самый распространенный запрос, выполняемый пользователями.

Таким образом, другой способ заключается в том, чтобы не включать столбцы evtrep и просто воссоздавать новое, немного другое событие, необходимое столько раз для диапазона. Но мне не нравится эта идея, как мысль о дублировании того, что многие данные заставляют меня съеживаться. Однако, если он будет гарантировать мне значительно более быстрые результаты (и, очевидно, запрос на поиск будет намного проще и быстрее), то я предполагаю, что это может оправдать дополнительное хранилище.

Что вы считаете лучшим планом? Или есть еще один, о котором я не думал/упоминал здесь?

Заранее благодарен!

Обновление 1: человек-б сделал хорошее предложение. Я считаю, что person-b предполагает, что моя таблица может быть не в первой нормальной форме, которая может быть истинной, если предположить, что многие (более 30%) событий не повторяются (в моем случае, однако, 80% + события, вероятно, повторят события). Тем не менее, я думаю, что мой вопрос должен возникнуть, поскольку в его первом обновлении предложенное пользователем изменение или добавление reptimes просто оттолкнуло обработку даты на задний план (что в моем случае является PHP), обработка которого я все еще должен учитывать. Но моя главная проблема (вопрос) заключается в следующем: каков самый быстрый способ в среднем на каждый запрос для вычисления дат и времени каждого события без ручного создания x количества записей для повторения событий?

ответ

1

Попробуйте нормализовать свои таблицы - вы будете отделять информацию о событии от (нескольких) дат и информации о повторении.

Обновление: Вот пример:
Таблица 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:

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 
) 

Затем, используя запрос, как это (непроверенные):

SELECT e.evttitle, r.reptimes FROM events e, repeats r WHERE e.eventid = 9 

Дополнительная информация (бот ч из той же направляющей) на Simple joins и Normalisation.

Это сделает вашу систему более гибкой и, надеюсь, быстрее.

+0

Удаленный предыдущий комментарий, как вы его разрешили. См. Мое обновление.Возможно, я не сказал себя хорошо в моем первоначальном вопросе. – Mike

+0

В таком случае я не уверен. :(Я буду держать это здесь. –