[Optimize] SQL Queries : Remove joins from account table

This commit is contained in:
Neozonz 2014-01-20 14:26:10 -08:00
parent bf484c4be2
commit a78141b5ce

View File

@ -350,10 +350,10 @@ class Statistics extends Base {
/** /**
* Get amount of shares for a specific user * Get amount of shares for a specific user
* @param account_id int User ID * @param username str username
* @return data array invalid and valid share counts * @return data array invalid and valid share counts
**/ **/
public function getUserShares($account_id) { public function getUserShares($username, $account_id) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
// Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL // Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL
if ($data = $this->memcache->get(STATISTICS_ALL_USER_SHARES)) { if ($data = $this->memcache->get(STATISTICS_ALL_USER_SHARES)) {
@ -362,19 +362,17 @@ class Statistics extends Base {
// We have no cached value, we return defaults // We have no cached value, we return defaults
return array('valid' => 0, 'invalid' => 0, 'donate_percent' => 0, 'is_anonymous' => 0); return array('valid' => 0, 'invalid' => 0, 'donate_percent' => 0, 'is_anonymous' => 0);
} }
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; if ($data = $this->memcache->get(__FUNCTION__ . $username)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT SELECT
ROUND(IFNULL(SUM(IF(our_result='Y', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS valid, ROUND(IFNULL(SUM(IF(our_result='Y', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS valid,
ROUND(IFNULL(SUM(IF(our_result='N', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS invalid ROUND(IFNULL(SUM(IF(our_result='N', IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty), 0)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS invalid
FROM " . $this->share->getTableName() . " AS s, FROM " . $this->share->getTableName() . "
" . $this->user->getTableName() . " AS u
WHERE WHERE
u.username = SUBSTRING_INDEX( s.username, '.', 1 ) username = '?.%'
AND UNIX_TIMESTAMP(s.time) >IFNULL((SELECT MAX(b.time) FROM " . $this->block->getTableName() . " AS b),0) AND UNIX_TIMESTAMP(time) >IFNULL((SELECT MAX(b.time) FROM " . $this->block->getTableName() . " AS b),0)");
AND u.id = ?"); if ($stmt && $stmt->bind_param("i", $username) && $stmt->execute() && $result = $stmt->get_result())
if ($stmt && $stmt->bind_param("i", $account_id) && $stmt->execute() && $result = $stmt->get_result()) return $this->memcache->setCache(__FUNCTION__ . $username, $result->fetch_assoc());
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_assoc());
return $this->sqlError(); return $this->sqlError();
} }
@ -495,10 +493,10 @@ class Statistics extends Base {
/** /**
* Fetch total user hashrate based on shares and archived shares * Fetch total user hashrate based on shares and archived shares
* @param account_id integer User ID * @param $username string username
* @return data integer Current Hashrate in khash/s * @return data integer Current Hashrate in khash/s
**/ **/
public function getUserHashrate($account_id, $interval=180) { public function getUserHashrate($username, $account_id, $interval=180) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
// Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL // Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL
if ($data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) { if ($data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) {
@ -507,60 +505,54 @@ class Statistics extends Base {
// We have no cached value, we return defaults // We have no cached value, we return defaults
return 0; return 0;
} }
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $username)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT SELECT
IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0), 0) AS hashrate IFNULL(IF(our_result='Y', ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / ? / 1000), 0), 0) AS hashrate
FROM ( FROM (
SELECT SELECT
s.id, s.our_result, IF(s.difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty) AS difficulty id, our_result, IF(s.difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty
FROM FROM
shares AS s, shares
accounts AS u WHERE username = '?.%'
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 ) AND time > DATE_SUB(now(), INTERVAL ? SECOND)
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND) AND our_result = 'Y'
AND s.our_result = 'Y'
AND u.id = ?
UNION UNION
SELECT SELECT
s.share_id, s.our_result, IF(s.difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty) AS difficulty share_id, our_result, IF(s.difficulty = 0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty) AS difficulty
FROM FROM
shares_archive AS s, shares_archive
accounts AS u WHERE username = '?.%'
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 ) AND time > DATE_SUB(now(), INTERVAL ? SECOND)
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND) AND our_result = 'Y'
AND s.our_result = 'Y'
AND u.id = ?
) AS temp"); ) AS temp");
if ($this->checkStmt($stmt) && $stmt->bind_param("iiiii", $interval, $interval, $account_id, $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result() ) if ($this->checkStmt($stmt) && $stmt->bind_param("iiiii", $username, $interval, $username, $interval) && $stmt->execute() && $result = $stmt->get_result() )
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->hashrate); return $this->memcache->setCache(__FUNCTION__ . $username, $result->fetch_object()->hashrate);
return $this->sqlError(); return $this->sqlError();
} }
public function getUserUnpaidPPSShares($account_id, $last_paid_pps_id) { public function getUserUnpaidPPSShares($username, $last_paid_pps_id) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $username)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT SELECT
ROUND(IFNULL(SUM(IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS total ROUND(IFNULL(SUM(IF(s.difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)), 0) / POW(2, (" . $this->config['difficulty'] . " - 16)), 0) AS total
FROM " . $this->share->getTableName() . " AS s FROM " . $this->share->getTableName() . "
JOIN " . $this->user->getTableName() . " AS a WHERE username = '?.%'
ON a.username = SUBSTRING_INDEX( s.username, '.', 1 ) AND id > ?
AND a.id = ? AND our_result = 'Y'");
AND s.id > ? if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $username, $last_paid_pps_id) && $stmt->execute() && $result = $stmt->get_result() )
WHERE our_result = 'Y'"); return $this->memcache->setCache(__FUNCTION__ . $username, $result->fetch_object()->total);
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $account_id, $last_paid_pps_id) && $stmt->execute() && $result = $stmt->get_result() )
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->total);
return $this->sqlError(); return $this->sqlError();
} }
/** /**
* Get average share difficulty across all workers for user * Get average share difficulty across all workers for user
* @param account_id int Account ID * @param username string username
* @param interval int Data interval in seconds * @param interval int Data interval in seconds
* @return double Share difficulty or 0 * @return double Share difficulty or 0
**/ **/
public function getUserShareDifficulty($account_id, $interval=180) { public function getUserShareDifficulty($username, $account_id, $interval=180) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
// Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL // Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL
if ($data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) { if ($data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) {
@ -569,27 +561,26 @@ class Statistics extends Base {
// We have no cached value, we return defaults // We have no cached value, we return defaults
return 0; return 0;
} }
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $username)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT SELECT
IFNULL(AVG(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 0) AS avgsharediff, IFNULL(AVG(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)), 0) AS avgsharediff,
COUNT(s.id) AS total COUNT(s.id) AS total
FROM " . $this->share->getTableName() . " AS s JOIN " . $this->user->getTableName() . " AS a FROM " . $this->share->getTableName() . " AS s
ON a.username = SUBSTRING_INDEX( s.username, '.', 1 ) WHERE username = '?.%'
WHERE s.time > DATE_SUB(now(), INTERVAL ? SECOND) AND time > DATE_SUB(now(), INTERVAL ? SECOND)
AND our_result = 'Y' AND our_result = 'Y');
AND a.id = ?"); if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $username, $interval) && $stmt->execute() && $result = $stmt->get_result() )
if ($this->checkStmt($stmt) && $stmt->bind_param("ii", $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__ . $username, $result->fetch_object()->avgsharediff);
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->avgsharediff);
return $this->sqlError(); return $this->sqlError();
} }
/** /**
* Same as getUserHashrate for Sharerate * Same as getUserHashrate for Sharerate
* @param account_id integer User ID * @param username string username
* @return data integer Current Sharerate in shares/s * @return data integer Current Sharerate in shares/s
**/ **/
public function getUserSharerate($account_id, $interval=180) { public function getUserSharerate($username, $account_id, $interval=180) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
// Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL // Dual-caching, try statistics cron first, then fallback to local, then fallbock to SQL
if ($data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) { if ($data = $this->memcache->getStatic(STATISTICS_ALL_USER_HASHRATES)) {
@ -598,54 +589,48 @@ class Statistics extends Base {
// We have no cached value, we return defaults // We have no cached value, we return defaults
return 0; return 0;
} }
if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; if ($this->getGetCache() && $data = $this->memcache->get(__FUNCTION__ . $username)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT SELECT
IFNULL(COUNT(*) / ?, 0) AS sharerate IFNULL(COUNT(*) / ?, 0) AS sharerate
FROM ( FROM (
SELECT SELECT
s.id id
FROM FROM
shares AS s, shares
accounts AS u WHERE username = '?.%'
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 ) AND time > DATE_SUB(now(), INTERVAL ? SECOND)
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND) AND our_result = 'Y'
AND s.our_result = 'Y'
AND u.id = ?
UNION UNION
SELECT SELECT
s.share_id share_id
FROM FROM
shares_archive AS s, shares_archive
accounts AS u WHERE username = '?.%'
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 ) AND time > DATE_SUB(now(), INTERVAL ? SECOND)
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND) AND our_result = 'Y'
AND s.our_result = 'Y'
AND u.id = ?
) AS temp"); ) AS temp");
if ($this->checkStmt($stmt) && $stmt->bind_param("iiiii", $interval, $interval, $account_id, $interval, $account_id) && $stmt->execute() && $result = $stmt->get_result() ) if ($this->checkStmt($stmt) && $stmt->bind_param("iiiii", $username, $interval, $username, $interval) && $stmt->execute() && $result = $stmt->get_result() )
return $this->memcache->setCache(__FUNCTION__ . $account_id, $result->fetch_object()->sharerate); return $this->memcache->setCache(__FUNCTION__ . $username, $result->fetch_object()->sharerate);
return $this->sqlError(); return $this->sqlError();
} }
/** /**
* Get hashrate for a specific worker * Get hashrate for a specific worker
* @param worker_id int Worker ID to fetch hashrate for * @param username string username
* @return data int Current hashrate in khash/s * @return data int Current hashrate in khash/s
**/ **/
public function getWorkerHashrate($worker_id,$interval=180) { public function getWorkerHashrate($worker_id, $interval=180) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
if ($data = $this->memcache->get(__FUNCTION__ . $worker_id)) return $data; if ($data = $this->memcache->get(__FUNCTION__ . $username)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 600 / 1000), 0) AS hashrate SELECT IFNULL(ROUND(SUM(IF(difficulty=0, POW(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 600 / 1000), 0) AS hashrate
FROM " . $this->share->getTableName() . " AS s, FROM " . $this->share->getTableName() . " AS
" . $this->user->getTableName() . " AS u WHERE username = '?'
WHERE u.username = SUBSTRING_INDEX( s.username, '.', 1 )
AND our_result = 'Y' AND our_result = 'Y'
AND s.time > DATE_SUB(now(), INTERVAL ? SECOND) AND time > DATE_SUB(now(), INTERVAL ? SECOND));
AND u.id = ?"); if ($this->checkStmt($stmt) && $stmt->bind_param("i", $username, $interval) && $stmt->execute() && $result = $stmt->get_result() )
if ($this->checkStmt($stmt) && $stmt->bind_param("i", $account_id) && $stmt->execute() && $result = $stmt->get_result() ) return $this->memcache->setCache(__FUNCTION__ . $username, $result->fetch_object()->hashrate);
return $this->memcache->setCache(__FUNCTION__ . $worker_id, $result->fetch_object()->hashrate);
return $this->sqlError(); return $this->sqlError();
} }
@ -726,43 +711,40 @@ class Statistics extends Base {
/** /**
* get Hourly hashrate for a user * get Hourly hashrate for a user
* @param account_id int User ID * @param username string Username
* @return data array NOT FINISHED YET * @return data array NOT FINISHED YET
**/ **/
public function getHourlyHashrateByAccount($account_id) { public function getHourlyHashrateByAccount($username) {
$this->debug->append("STA " . __METHOD__, 4); $this->debug->append("STA " . __METHOD__, 4);
if ($data = $this->memcache->get(__FUNCTION__ . $account_id)) return $data; if ($data = $this->memcache->get(__FUNCTION__ . $username)) return $data;
$stmt = $this->mysqli->prepare(" $stmt = $this->mysqli->prepare("
SELECT SELECT
a.id, IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 3600 / 1000), 0) AS hashrate,
IFNULL(ROUND(SUM(IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 3600 / 1000), 0) AS hashrate, HOUR(time) AS hour
HOUR(s.time) AS hour FROM " . $this->share->getTableName() . "
FROM " . $this->share->getTableName() . " AS s, accounts AS a
WHERE time <= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60)) WHERE time <= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60))
AND time >= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60)) - INTERVAL 24 HOUR AND time >= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60)) - INTERVAL 24 HOUR
AND our_result = 'Y' AND our_result = 'Y'
AND a.username = SUBSTRING_INDEX( s.username, '.', 1 ) AND username = '?.%'
AND a.id = ?
GROUP BY HOUR(time) GROUP BY HOUR(time)
UNION UNION
SELECT SELECT
share_id, share_id,
IFNULL(ROUND(SUM(IF(s.difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), s.difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 3600 / 1000), 0) AS hashrate, IFNULL(ROUND(SUM(IF(difficulty=0, pow(2, (" . $this->config['difficulty'] . " - 16)), difficulty)) * POW(2, " . $this->config['target_bits'] . ") / 3600 / 1000), 0) AS hashrate,
HOUR(s.time) AS hour HOUR(time) AS hour
FROM " . $this->share->getArchiveTableName() . " AS s, accounts AS a FROM " . $this->share->getArchiveTableName() . "
WHERE time <= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60)) WHERE time <= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60))
AND time >= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60)) - INTERVAL 24 HOUR AND time >= FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(NOW())/(60*60))*(60*60)) - INTERVAL 24 HOUR
AND our_result = 'Y' AND our_result = 'Y'
AND a.username = SUBSTRING_INDEX( s.username, '.', 1 ) AND username = '?.%'
AND a.id = ?
GROUP BY HOUR(time)"); GROUP BY HOUR(time)");
if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $account_id, $account_id) && $stmt->execute() && $result = $stmt->get_result()) { if ($this->checkStmt($stmt) && $stmt->bind_param('ii', $username, $username) && $stmt->execute() && $result = $stmt->get_result()) {
$iStartHour = date('G'); $iStartHour = date('G');
// Initilize array // Initilize array
for ($i = 0; $i < 24; $i++) $aData[($iStartHour + $i) % 24] = 0; for ($i = 0; $i < 24; $i++) $aData[($iStartHour + $i) % 24] = 0;
// Fill data // Fill data
while ($row = $result->fetch_assoc()) $aData[$row['hour']] = $row['hashrate']; while ($row = $result->fetch_assoc()) $aData[$row['hour']] = $row['hashrate'];
return $this->memcache->setCache(__FUNCTION__ . $account_id, $aData); return $this->memcache->setCache(__FUNCTION__ . $username, $aData);
} }
return $this->sqlError(); return $this->sqlError();
} }