Просмотр исходного кода

Simplify SQL in statistics

Reduce the use of product-specific date functions. Improve performances.
Remove redundant functions.
Alexandre Alapetite 9 лет назад
Родитель
Сommit
ccb56bcbf3
3 измененных файлов с 39 добавлено и 113 удалено
  1. 29 7
      app/Controllers/statsController.php
  2. 10 51
      app/Models/StatsDAO.php
  3. 0 55
      app/Models/StatsDAOSQLite.php

+ 29 - 7
app/Controllers/statsController.php

@@ -18,6 +18,27 @@ class FreshRSS_stats_Controller extends Minz_ActionController {
 		Minz_View::prependTitle(_t('admin.stats.title') . ' · ');
 	}
 
+	private function convertToSerie($data) {
+		$serie = array();
+
+		foreach ($data as $key => $value) {
+			$serie[] = array($key, $value);
+		}
+
+		return $serie;
+	}
+
+	private function convertToPieSerie($data) {
+		$serie = array();
+
+		foreach ($data as $value) {
+			$value['data'] = array(array(0, (int) $value['data']));
+			$serie[] = $value;
+		}
+
+		return $serie;
+	}
+
 	/**
 	 * This action handles the statistic main page.
 	 *
@@ -33,10 +54,11 @@ class FreshRSS_stats_Controller extends Minz_ActionController {
 		$statsDAO = FreshRSS_Factory::createStatsDAO();
 		Minz_View::appendScript(Minz_Url::display('/scripts/flotr2.min.js?' . @filemtime(PUBLIC_PATH . '/scripts/flotr2.min.js')));
 		$this->view->repartition = $statsDAO->calculateEntryRepartition();
-		$this->view->count = $statsDAO->calculateEntryCount();
-		$this->view->average = $statsDAO->calculateEntryAverage();
-		$this->view->feedByCategory = $statsDAO->calculateFeedByCategory();
-		$this->view->entryByCategory = $statsDAO->calculateEntryByCategory();
+		$entryCount = $statsDAO->calculateEntryCount();
+		$this->view->count = $this->convertToSerie($entryCount);
+		$this->view->average = round(array_sum(array_values($entryCount)) / count($entryCount), 2);
+		$this->view->feedByCategory = $this->convertToPieSerie($statsDAO->calculateFeedByCategory());
+		$this->view->entryByCategory = $this->convertToPieSerie($statsDAO->calculateEntryByCategory());
 		$this->view->topFeed = $statsDAO->calculateTopFeed();
 	}
 
@@ -118,11 +140,11 @@ class FreshRSS_stats_Controller extends Minz_ActionController {
 		$this->view->days = $statsDAO->getDays();
 		$this->view->months = $statsDAO->getMonths();
 		$this->view->repartition = $statsDAO->calculateEntryRepartitionPerFeed($id);
-		$this->view->repartitionHour = $statsDAO->calculateEntryRepartitionPerFeedPerHour($id);
+		$this->view->repartitionHour = $this->convertToSerie($statsDAO->calculateEntryRepartitionPerFeedPerHour($id));
 		$this->view->averageHour = $statsDAO->calculateEntryAveragePerFeedPerHour($id);
-		$this->view->repartitionDayOfWeek = $statsDAO->calculateEntryRepartitionPerFeedPerDayOfWeek($id);
+		$this->view->repartitionDayOfWeek = $this->convertToSerie($statsDAO->calculateEntryRepartitionPerFeedPerDayOfWeek($id));
 		$this->view->averageDayOfWeek = $statsDAO->calculateEntryAveragePerFeedPerDayOfWeek($id);
-		$this->view->repartitionMonth = $statsDAO->calculateEntryRepartitionPerFeedPerMonth($id);
+		$this->view->repartitionMonth = $this->convertToSerie($statsDAO->calculateEntryRepartitionPerFeedPerMonth($id));
 		$this->view->averageMonth = $statsDAO->calculateEntryAveragePerFeedPerMonth($id);
 	}
 }

+ 10 - 51
app/Models/StatsDAO.php

@@ -61,14 +61,15 @@ SQL;
 	 */
 	public function calculateEntryCount() {
 		$count = $this->initEntryCountArray();
-		$period = self::ENTRY_COUNT_PERIOD;
+		$midnight = mktime(0, 0, 0);
+		$oldest = $midnight - (self::ENTRY_COUNT_PERIOD * 86400);
 
 		// Get stats per day for the last 30 days
 		$sql = <<<SQL
-SELECT DATEDIFF(FROM_UNIXTIME(e.date), NOW()) AS day,
-COUNT(1) AS count
-FROM {$this->prefix}entry AS e
-WHERE FROM_UNIXTIME(e.date, '%Y%m%d') BETWEEN DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -{$period} DAY), '%Y%m%d') AND DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -1 DAY), '%Y%m%d')
+SELECT FLOOR((date - {$midnight}) / 86400) AS day,
+COUNT(*) as count
+FROM {$this->prefix}entry
+WHERE date >= {$oldest} AND date < {$midnight}
 GROUP BY day
 ORDER BY day ASC
 SQL;
@@ -80,28 +81,7 @@ SQL;
 			$count[$value['day']] = (int) $value['count'];
 		}
 
-		return $this->convertToSerie($count);
-	}
-
-	/**
-	 * Calculates entry average per day on a 30 days period.
-	 *
-	 * @return integer
-	 */
-	public function calculateEntryAverage() {
-		$period = self::ENTRY_COUNT_PERIOD;
-
-		// Get stats per day for the last 30 days
-		$sql = <<<SQL
-SELECT COUNT(1) / {$period} AS average
-FROM {$this->prefix}entry AS e
-WHERE FROM_UNIXTIME(e.date, '%Y%m%d') BETWEEN DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -{$period} DAY), '%Y%m%d') AND DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -1 DAY), '%Y%m%d')
-SQL;
-		$stm = $this->bd->prepare($sql);
-		$stm->execute();
-		$res = $stm->fetch(PDO::FETCH_NAMED);
-
-		return round($res['average'], 2);
+		return $count;
 	}
 
 	/**
@@ -173,7 +153,7 @@ SQL;
 			$repartition[(int) $value['period']] = (int) $value['count'];
 		}
 
-		return $this->convertToSerie($repartition);
+		return $repartition;
 	}
 
 	/**
@@ -276,7 +256,7 @@ SQL;
 		$stm->execute();
 		$res = $stm->fetchAll(PDO::FETCH_ASSOC);
 
-		return $this->convertToPieSerie($res);
+		return $res;
 	}
 
 	/**
@@ -301,7 +281,7 @@ SQL;
 		$stm->execute();
 		$res = $stm->fetchAll(PDO::FETCH_ASSOC);
 
-		return $this->convertToPieSerie($res);
+		return $res;
 	}
 
 	/**
@@ -351,27 +331,6 @@ SQL;
 		return $stm->fetchAll(PDO::FETCH_ASSOC);
 	}
 
-	protected function convertToSerie($data) {
-		$serie = array();
-
-		foreach ($data as $key => $value) {
-			$serie[] = array($key, $value);
-		}
-
-		return $serie;
-	}
-
-	protected function convertToPieSerie($data) {
-		$serie = array();
-
-		foreach ($data as $value) {
-			$value['data'] = array(array(0, (int) $value['data']));
-			$serie[] = $value;
-		}
-
-		return $serie;
-	}
-
 	/**
 	 * Gets days ready for graphs
 	 *

+ 0 - 55
app/Models/StatsDAOSQLite.php

@@ -2,61 +2,6 @@
 
 class FreshRSS_StatsDAOSQLite extends FreshRSS_StatsDAO {
 
-	/**
-	 * Calculates entry count per day on a 30 days period.
-	 * Returns the result as a JSON object.
-	 *
-	 * @return JSON object
-	 */
-	public function calculateEntryCount() {
-		$count = $this->initEntryCountArray();
-		$period = parent::ENTRY_COUNT_PERIOD;
-
-		// Get stats per day for the last 30 days
-		$sql = <<<SQL
-SELECT round(julianday(e.date, 'unixepoch') - julianday('now')) AS day,
-COUNT(1) AS count
-FROM {$this->prefix}entry AS e
-WHERE strftime('%Y%m%d', e.date, 'unixepoch')
-	BETWEEN strftime('%Y%m%d', 'now', '-{$period} days')
-	AND strftime('%Y%m%d', 'now', '-1 day')
-GROUP BY day
-ORDER BY day ASC
-SQL;
-		$stm = $this->bd->prepare($sql);
-		$stm->execute();
-		$res = $stm->fetchAll(PDO::FETCH_ASSOC);
-
-		foreach ($res as $value) {
-			$count[(int) $value['day']] = (int) $value['count'];
-		}
-
-		return $this->convertToSerie($count);
-	}
-
-	/**
-	 * Calculates entry average per day on a 30 days period.
-	 *
-	 * @return integer
-	 */
-	public function calculateEntryAverage() {
-		$period = self::ENTRY_COUNT_PERIOD;
-
-		// Get stats per day for the last 30 days
-		$sql = <<<SQL
-SELECT COUNT(1) / {$period} AS average
-FROM {$this->prefix}entry AS e
-WHERE strftime('%Y%m%d', e.date, 'unixepoch')
-	BETWEEN strftime('%Y%m%d', 'now', '-{$period} days')
-	AND strftime('%Y%m%d', 'now', '-1 day')
-SQL;
-		$stm = $this->bd->prepare($sql);
-		$stm->execute();
-		$res = $stm->fetch(PDO::FETCH_NAMED);
-
-		return round($res['average'], 2);
-	}
-
 	protected function calculateEntryRepartitionPerFeedPerPeriod($period, $feed = null) {
 		if ($feed) {
 			$restrict = "WHERE e.id_feed = {$feed}";