дизайн для БД, когда необходимо знать последнюю версию для чего-то

#mysql #database

#mysql #База данных

Вопрос:

допустим, у меня есть следующие объекты:

 Site: 

idSite,
name
and other static data. 

Test:

idTest
idSite
name
and other static data.

Site Version:

idSiteVersion,
idSite
name of version


Test Result:

ןdTestResult
idSiteVersion, 
idTest,
timeEnded
  

для каждого сайта есть список тестов, которые зарегистрированы для него.

теперь я хочу знать для каждого из них site version последние testresults данные, сгруппированные по idTest . а также для тех, кто не тестировался, с нулевым значением. (b)

Я внедрил БД для этого.

но у меня возникли проблемы с получением запроса, который я перечислил (b), это занимает много времени.

Я подумываю о его переделке. любые советы помогут

новый будет состоять из таблицы, LATEST которая будет действовать как кэш,
поэтому я буду использовать триггеры при вставке, чтобы обновить нужную строку,
и выберу из нее.

это верно?
должен ли я переделать это?

запрос:

 select `tr1`.`id` AS `id`,
`dsv`.`idSite_id` AS `idSite`,
`tr1`.`idSiteVersion_id` AS `idSiteVersion`,
`tr1`.`idTest_id` AS `idTest`,
`tr1`.`result` AS `result`,
`tr1`.`timeStarted` AS `timeStarted`,
 from 
`dash`.`testresult` `tr1` 
join `dash`.`siteversion` `dsv` on `dsv`.`id` = `tr1`.`idSiteVersion_id`
join `dash`.`test` `dtest` on `dtest`.`id` = `tr1`.`idTest_id` 
where `dtest`.`ignored` = 0 and `tr1`.`timeEnd` = 
( select max(`tr2`.`timeEnd`) from `dash`.`testresult` `tr2` 
    where 
       ((`tr2`.`idTest_id` = `tr1`.`idTest_id`) and 
       (`tr2`.`idSiteVersion_id` = `tr1`.`idSiteVersion_id`) and 
       (`tr2`.`timeEnd` is not null)))
  

Комментарии:

1. Удалите idSite из TestResult, потому что вы можете получить его через тест.

2. Было бы полезно, если бы вы опубликовали свой запрос. Если у вас медленный запрос, как правило, первое, что нужно сделать, это профилировать его, чтобы убедиться, что он использует правильные индексы и т.д.

3. @Jason, просто show profile ?

4. @shevski покажите нам запрос. Если это занимает значительное количество времени, это, скорее всего, может быть оптимизировано без необходимости реструктуризации.

5. @MatthewCox это занимает больше нескольких секунд, я опубликую это, когда буду работать

Ответ №1:

Попробуйте это так:

 SELECT
  tr1.id AS id,
  dsv.idSite_id AS idSite,
  tr1.idSiteVersion_id AS idSiteVersion,
  tr1.idTest_id AS idTest,
  tr1.result AS result,
  tr1.timeStarted AS timeStarted,
FROM 
  dash.testresult AS tr1 
  NATURAL JOIN (
    SELECT idTest_id, idSiteVersion_id, MAX(timeEnd) AS timeEnd
    FROM dash.testresult
    WHERE timeEnd IS NOT NULL
    GROUP BY idTest_id, idSiteVersion_id
  ) AS tr2
  JOIN dash.siteversion AS dsv
    ON dsv.id = tr1.idSiteVersion_id
  JOIN dash.test AS dtest
    ON dtest.id = tr1.idTest_id AND dtest.ignored = 0
  

Кроме того, вы определенно хотите создать индекс на dash.testresult (idTest_id, idSiteVersion_id, timeEnd) , если у вас его еще нет.

Комментарии:

1. AND подразумевается, что конец запроса будет WHERE ?

2. Вы тоже можете использовать WHERE dtest.ignored = 0 , но я сделал это частью условия объединения, так как мне так показалось приятнее. Здесь это не должно иметь никакого значения в любом случае.

3. этот запрос действительно сократил время выполнения