降低查询处理能力

时间:2016-06-05 22:25:38

标签: mysql database performance processing-efficiency

我正在处理一个每分钟多次添加新行的表。正如我经常需要运行下面的查询一样,我认为这是最近滞后峰值的原因。

有什么方法可以让这个查询更有效率吗?

SELECT IFNULL((SELECT SUM(amount) 
  FROM transactions 
  WHERE to_account=:account), 0) - IFNULL((SELECT SUM(amount) 
  FROM transactions WHERE from_account=:account), 0) as balance;

CREATE TABLE IF NOT EXISTS `transactions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `from_account` int(11) NOT NULL,
  `to_account` int(11) NOT NULL,
  `amount` int(11) unsigned NOT NULL,
  `fee` int(11) NOT NULL DEFAULT '0'
  `ip` varchar(39) DEFAULT NULL,
  `time` int(10) NOT NULL,
  `type` enum('CLAIM','REFERRAL','DEPOSIT','WITHDRAWAL') NOT NULL,
  `is_processed` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `from_account` (`from_account`),
  KEY `to_account` (`to_account`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=24099 ;

3 个答案:

答案 0 :(得分:0)

看起来你的两个表读数是

SELECT SUM(amount) 
  FROM transactions
 WHERE from_account = constant

SELECT SUM(amount) 
  FROM transactions
 WHERE to_account = constant

第一个可以通过(from_account,amount)上的复合索引进行优化,因为它允许通过索引范围扫描来满足查询。第二个查询可以用类似的索引来满足。您可以删除from_account和to_account上的索引,用这些复合索引替换它们。

您的INSERT和SELECT查询之间仍可能存在争用。但是SELECT的索引应该减少。

答案 1 :(得分:0)

好的,您遇到的滞后可能不是100%可预防的,但有一个小的索引技巧可以减少这种滞后的机会:

  

对您使用的所有值使用多列索引,或在查询中返回。

在你的情况下:

CREATE INDEX idx_nn_1 ON transactions(from_account,amount);
CREATE INDEX idx_nn_2 ON transactions(to_account,amount);

这样做是要注意不必阅读数据库中的真实记录来获得结果。

有一个缺点:在多列索引中更新/插入记录比单列索引慢。这里的权衡只能通过测试确定。

答案 2 :(得分:0)

此外,简化查询:

SELECT 
    ( SELECT IFNULL(SUM(amount), 0) FROM transactions WHERE to_account = ... ) -
    ( SELECT IFNULL(SUM(amount), 0) FROM transactions WHERE from_account = ... )
                  AS balance;

该表似乎没有变化,但检查您的innodb_buffer_pool_size

设置