Php SQL查询优化-多查询或DAYOFYEAR()?
我需要在几个条件下运行查询,这些条件将导致大数据集。鉴于所有条件都是直截了当的,我需要关于速度优化方面的两个问题的建议: 1) 如果我需要在过去10年中每年的4月1日至6月20日期间运行这些查询,我有两种选择: a。运行查询10次Php SQL查询优化-多查询或DAYOFYEAR()?,php,mysql,Php,Mysql,我需要在几个条件下运行查询,这些条件将导致大数据集。鉴于所有条件都是直截了当的,我需要关于速度优化方面的两个问题的建议: 1) 如果我需要在过去10年中每年的4月1日至6月20日期间运行这些查询,我有两种选择: a。运行查询10次 $year = 2015; $start_month_date = "-04-01"; $end_month_date = "-06-20"; for($i=0;$i<10;$i++){ $start = $year.$start_month_date;
$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;
}
我知道闰年的天数与其他年份相差一天,但我可以接受。我感觉1.b更优化,只是想验证一下
2) 我有一个包含两个子查询的大查询。当我想按日期限制结果时,我应该将条件放在子查询的内部还是外部
a。内部子查询意味着它必须两次验证条件
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`
b。外部子查询意味着它将验证一次,但必须加入一个更大的数据集(我需要为其设置SQL\u BIG\u SELECTS=1)
同样,在我看来2.a更为优化,但需要您的建议
谢谢(1)当SQL引擎可以利用事件日期
上的索引时,使用$start和$end之间的事件日期运行查询10次会更快。这可能很重要,但这取决于查询的其余部分
另外,由于您要对整个数据集进行排序,因此运行10个查询可能会快一点。这是因为排序是O(n log(n)),这意味着对较大的数据集进行排序需要更长的时间。例如,对100行进行排序可能需要X个时间单位。对1000行进行排序可能需要X*10*log(10)个时间单位。但是,对100行进行10次排序只需要X*10(这是为了解释)
(2) 如果可以在MySQL中避免子查询,请不要使用它们。子查询被具体化,这增加了额外的开销。此外,它们还阻止使用索引。如果需要使用子查询,请在子查询中尽可能多地过滤数据。这减少了需要存储的数据。我假设您在10年内有很多行,否则这不会是什么问题
现在最好的办法是对您计划使用的不同查询做一些解释,这可能会告诉您它可以使用哪个索引,因为目前我们不知道它们(您没有发布表的结构)
1.b。在where子句中使用一个函数,这样会很糟糕,因为它不能使用日期索引(假设有索引)。这将读取整个表
您可以做的一件事是让数据库使用UNION将10个查询的结果集连接在一起。Mysql将加入结果而不是php。。。(见附件)
正如戈登所说,尽可能多地过滤数据。不过,您可以使用EXPLAIN,而不是盲目尝试该选项,数据库将帮助您决定哪一个选项最有意义。非常感谢。。这就是为什么我总是在这里接受建议,所以。。。只是一些确认:(1)基本上查询与示例2相同,有两个子查询。我有3个字段的条件,除了event_date,我只使用额外的条件:case='A'和month='JUL',诸如此类的东西。所有这3个字段都在mysql数据库表中建立索引。因此,我将按照您的建议使用10个查询方法。(2)因此,我将在子查询(如果我需要使用它们)中尽可能多地放置条件,而不是将它们放在连接数据集的末尾。如果您具有相等条件,则在案例、月份、事件_日期
上的索引将是一个很好的索引选择。谢谢。。。我确实有这3方面的索引。。但是,月份和大小写是相等条件的,事件的日期是以BETWEENokay为界的,基本上我需要在3个字段上设置条件,并且所有这3个字段都被索引。非常感谢。。你们两个都同意相同的方法(其中一个与我的想法相反:)。所以我会按照你们的经验建议,我记得mysql有时在日期范围超过30天(即mysql 5.1)时不使用索引,所以即使这看起来是最好的索引,它也会做一些意想不到的事情。因此,您应该检查它使用的索引。它将无法使用所有3:)
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`
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`