Pokud máte index s created
jako úvodní sloupec může být MySQL schopno provést zpětné skenování. Pokud máte 24hodinové období, které neobsahuje žádné události, můžete vracet řádek, který NENÍ z tohoto období. Abyste se ujistili, že v tomto období zaznamenáváte řádek, musíte do created
zahrnout spodní hranici také něco jako toto:
SELECT * FROM `eventos`
WHERE ...
AND `created` < FROM_UNIXTIME( {$timestamp} )
AND `created` >= DATE_ADD(FROM_UNIXTIME( {$timestamp} ),INTERVAL -24 HOUR)
ORDER BY `created` DESC
LIMIT 1
Myslím, že hlavním klíčem k výkonu je zde index s created
jako úvodní sloupec spolu se všemi (nebo většinou) ostatními sloupci, na které odkazuje klauzule WHERE, a ujistěte se, že váš dotaz používá index.
Pokud potřebujete jiný časový interval, až na druhý, lze tento přístup snadno zobecnit.
SELECT * FROM `eventos`
WHERE ...
AND `created` < DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL 0*{$nsecs} SECOND)
AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*{$nsecs} SECOND)
ORDER BY `created` DESC
LIMIT 1
Z vašeho kódu to vypadá, že 24hodinové periody jsou ohraničeny v libovolném čase... pokud funkce času vrací např. 1341580800 ('2012-07-06 13:20'), pak všech deset menstruací bude od 13:20 daného dne do 13:20 následujícího dne.
(POZNÁMKA:ujistěte se, že pokud je vaším parametrem celé číslo unixového časového razítka, že jej databáze interpretuje správně.)
Mohlo by být efektivnější stáhnout deset řádků v jednom dotazu. Pokud existuje záruka, že 'časové razítko' je jedinečné, je možné takový dotaz vytvořit, ale text dotazu bude podstatně složitější než ten, který máte nyní. Mohli bychom se pohrát se získáním MAX (timestamp_) v každém období a pak to spojit, abychom dostali řádek... ale to bude opravdu komplikované.
Pokud bych se chtěl pokusit vytáhnout všech deset řádků, pravděpodobně bych zkusil použít UNION ALL
přístup, ne moc hezký, ale aspoň by se to dalo vyladit.
SELECT p0.*
FROM ( SELECT * FROM `eventos` WHERE ...
AND `created` < DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL 0*24 HOUR)
AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*24 HOUR)
ORDER BY `created` DESC LIMIT 1
) p0
UNION ALL
SELECT p1.*
FROM ( SELECT * FROM `eventos` WHERE ...
AND `created` < DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -1*24 HOUR)
AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -2*24 HOUR)
ORDER BY `created` DESC LIMIT 1
) p1
UNION ALL
SELECT p2.*
FROM ( SELECT * FROM `eventos` WHERE ...
AND `created` < DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -2*24 HOUR)
AND `created` >= DATE_ADD(FROM_UNIXTIME({$timestamp}),INTERVAL -3*24 HOUR)
ORDER BY `created` DESC LIMIT 1
) p2
UNION ALL
SELECT p3.*
FROM ...
Opět by se to dalo zobecnit a přejít jako argument během několika sekund. Nahraďte HOUR za SECOND a nahraďte '24' parametrem vazby, který má počet sekund.
Je to dost táhlé, ale mělo by to běžet v pořádku.
Dalším opravdu chaotickým a komplikovaným způsobem, jak to získat zpět v jedné sadě výsledků, by bylo použít inline zobrazení k získání koncového časového razítka pro deset období, něco takového:
SELECT p.period_end
FROM (SELECT DATE_ADD(t.t_,INTERVAL -1 * i.i_* {$nsecs} SECOND) AS period_end
FROM (SELECT FROM_UNIXTIME( {$timestamp} ) AS t_) t
JOIN (SELECT 0 AS i_
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
) i
) p
A pak to připojte ke svému stolu ...
ON `created` < p.period_end
AND `created` >= DATE_ADD(p.period_end,INTERVAL -1 * {$nsecs} SECOND)
A stáhnout MAX (vytvořeno) pro každé období GROUP BY p.period_end, zabalit to do vloženého zobrazení.
A pak to připojte zpět ke svému stolu, abyste získali každý řádek.
Ale to je opravdu, opravdu chaotické, těžko pochopitelné a pravděpodobně to nebude rychlejší (nebo efektivnější) než to, co již děláte. Největším zlepšením, které byste mohli udělat, je čas potřebný ke spuštění 9 vašich dotazů.