SQL查询优化 - 多个查询还是DAYOFYEAR()?

时间:2015-08-23 02:23:13

标签: php mysql

我需要运行具有多个条件的查询,这些条件将导致大型数据集。虽然所有条件都是直截了当的,但我需要就速度优化方面的2个问题提出建议:

1)如果我需要在过去10年的4月1日至6月20日之间运行这些查询,我知道有两种选择:

一个。运行查询10次

$year = 2015;
$start_month_date = "-04-01";
$end_month_date = "-06-20";
for($i=0;$i<10;$i++){
  $start = $year.$start_month_date;
  $end = $year.$start_month_date;
  $result = mysql_query("....... WHERE .... AND `event_date` BETWEEN $start AND $end");
  // PUSH THE RESULT TO AN ARRAY
  $year = $year - 1;
}

湾单次运行查询,但查询将按DayOfYear进行比较(因此查询必须将每个日期转换为DayOfYear)

$start = Date("z", strtotime("2015-04-01")) + 1;
$end = Date("z", strtotime("2015-06-20")) + 1;
$result = mysql_query("....... WHERE .... AND DAYOFYEAR(`event_date`) BETWEEN $start AND $end");

我知道闰年与其他年份的日间差异为1天,但我可以忍受。我感觉1.b更优化,只是想验证。

2)我有一个带有2个子查询的大型查询。当我想按日期限制结果时,我应该把条件放在子查询的内部或外部吗?

一个。内部子查询意味着它必须两次验证条件

SELECT X.a,X.b,Y.c FROM 
(SELECT * FROM mytable WHERE `event_date` BETWEEN '$startdate' AND '$enddate' AND `case` = 'AAA' AND .......) X
(SELECT * FROM mytable WHERE `event_date` BETWEEN '$startdate' AND '$enddate' AND `case` = 'BBB' AND .......) Y
WHERE X.`event_date` = Y.`event_date` AND ........... ORDER BY `event_date`

湾外部子查询意味着它将验证一次,但必须加入更大的数据集(我需要设置SQL_BIG_SELECTS = 1)

SELECT X.a,X.b,Y.c FROM 
(SELECT * FROM mytable WHERE `case` = 'AAA' AND .......) X
(SELECT * FROM mytable WHERE `case` = 'BBB' AND .......) Y
WHERE X.`event_date` = Y.`event_date` AND X.`event_date` BETWEEN '$startdate' AND '$enddate' AND ........... ORDER BY `event_date`

同样,在我看来2.a更优化,但请求您的建议。

由于

2 个答案:

答案 0 :(得分:1)

(1)当SQL引擎可以利用event_date BETWEEN $start AND $end上的索引时,使用event_date运行查询10次会更快。这可能很重要,但这取决于查询的其余部分。

此外,由于您要订购整个数据集,因此运行10个查询的速度可能会快一些。这是因为排序是O(n log(n)),这意味着对较大的数据集进行排序需要更长的时间。例如,排序100行可能需要X个时间单位。排序1000行可能需要X * 10 * log(10)个时间单位。但是,排序100行10次只需要X * 10(这是出于解释目的)。

(2)如果可以在MySQL中避免使用子查询,请不要使用子查询。子查询已实现,这增加了额外的开销。此外,他们然后阻止使用索引。如果需要使用子查询,请在子查询中尽可能多地过滤数据。这减少了需要存储的数据。

答案 1 :(得分:1)

我假设你有超过10年的大量行,否则这不是一个大问题。

现在最好的办法是对您计划使用的不同查询做一些解释,这可能会告诉您它可以使用哪个索引,因为我们目前还不知道它们(您没有发布表的结构)

1.B。在where子句中使用一个函数,所以它会很糟糕,因为它不能使用索引作为日期(假设有一个)。所以这将读取整个表格

您可以做的一件事是,要求数据库使用UNION一起加入10个查询的结果集。 Mysql会加入结果而不是php ...(参见https://dev.mysql.com/doc/refman/5.0/en/union.html

2 - 正如戈登所说,尽可能过滤数据。然而,不是盲目地尝试选项,你可以使用EXPLAIN,数据库将帮助你决定哪一个最有意义。