Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 如何优化这个简单的连接+;按查询订购?_Mysql_Sql_Query Optimization - Fatal编程技术网

Mysql 如何优化这个简单的连接+;按查询订购?

Mysql 如何优化这个简单的连接+;按查询订购?,mysql,sql,query-optimization,Mysql,Sql,Query Optimization,我有两个mysql表: /* Table users */ CREATE TABLE IF NOT EXISTS `users` ( `Id` int(10) unsigned NOT NULL AUTO_INCREMENT, `DateRegistered` datetime NOT NULL, PRIMARY KEY (`Id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /* Table statistics_user */ CREATE T

我有两个mysql表:

/* Table users */
CREATE TABLE IF NOT EXISTS `users` (
  `Id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `DateRegistered` datetime NOT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/* Table statistics_user */
CREATE TABLE IF NOT EXISTS `statistics_user` (
  `UserId` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `Sent_Views` int(10) unsigned NOT NULL DEFAULT '0',
  `Sent_Winks` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`UserId`),
  CONSTRAINT `statistics_user_ibfk_1` FOREIGN KEY (`UserId`) REFERENCES `users` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
两个表都填充了10.000个随机行,以便使用以下程序进行测试:

DELIMITER //
CREATE DEFINER=`root`@`localhost` PROCEDURE `FillUsersStatistics`(IN `cnt` INT)
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE dt DATE;
DECLARE Winks INT DEFAULT 1;
DECLARE Views INT DEFAULT 1;

WHILE (i<=cnt) DO
        SET dt = str_to_date(concat(floor(1 + rand() * (9-1)),'-',floor(1 + rand() * (28 -1)),'-','2011'),'%m-%d-%Y');

        INSERT INTO users (Id, DateRegistered) VALUES(i, dt);

        SET Winks = floor(1 + rand() * (30-1));
        SET Views = floor(1 + rand() * (30-1));
        INSERT INTO statistics_user (UserId, Sent_Winks, Sent_Views) VALUES (i, Winks, Views);

     SET i=i+1;
END WHILE;

END//
DELIMITER ;
CALL `FillUsersStatistics`(10000);
。。我明白这一点:

Id  select_type table   type    possible_keys   key     key_len     ref             rows    extra
1   SIMPLE      t1      ALL     PRIMARY         (NULL)  (NULL)      (NULL)          10037   Using temporary; Using filesort
1   SIMPLE      t2      eq_ref  PRIMARY         PRIMARY 4           test2.t2.UserId 1   
当两个表都有超过500K行时,上面的查询会变得非常慢。我猜这是因为“使用临时的;在查询解释中使用filesort


如何优化上述查询以使其运行更快?

您应该尝试内部联接,而不是笛卡尔积,接下来您可以做的是根据注册日期进行分区。

我无法确定ORDER BY是最要命的,因为它无法正确索引。这里有一个可行的解决方案,如果不是特别漂亮的话

首先,假设您有一个名为
Score
的列,用于存储用户的当前分数。每当用户的
Sent_视图
Sent_视图
发生更改时,请修改
得分
列以匹配。这可能是通过触发器实现的(我对触发器的经验有限),或者肯定是通过更新
Sent\u视图
Sent\u Winks
字段的相同代码实现的。此更改不需要知道DATEDIFF部分,因为它只需除以旧的
Sent\u Views+Sent\u Winks
之和,然后乘以新的部分即可

现在,您只需每天更改一次
Score
列(如果您对用户注册的准确小时数不挑剔的话)。这可以通过cron作业运行的脚本来完成

然后,只需索引
得分
列并选择离开


注意:编辑以删除不正确的第一次尝试。

我提供我的评论作为答案:

确定一个未来的日期,远到不影响你的申请,比如说5000年。在分数计算中,将当前日期替换为未来日期。分数计算现在对于所有意图和目的都是绝对的,并且可以在更新眨眼和视图时计算(通过存储过程或atrigger(mysql是否有触发器?)

score
列添加到
statistics\u user
表中,以存储计算的分数并在其上定义索引

您的SQL可以重写为:

SELECT
   UserId, score  
FROM
  statistics_user 
ORDER BY score DESC

如果您需要实际分数,只需一个常量乘法就可以轻松计算出来,如果它与mysql索引选择相冲突,之后就可以进行计算。

您不应该在用户中注册索引日期吗

您正在根据无法索引的动态属性(now())对整个结果进行排序。如果你能在统计数据更新时计算分数,并在分数上维护一个索引,你会有更好的机会。只是一个想法:如果你不是现在(),而是使用一个很长的未来时间(就像你要计算这个结果,比如说在2500年),绝对分数会有所不同,但相对顺序会保持不变。因此,您可以维护一个分数索引,该索引将反映您想要的排序,并且可能会重新计算排序结果的实际分数。真正的问题是:为什么要维护两个表(实际上)之间具有1::1关系?但是使用to_days()不能给出正确的排序顺序。如果我们都有1000次眨眼和观看,但我昨天注册了,你100天前注册了,你会得到更高的分数,但应该是相反的。谢谢你指出……显然我的大脑没有正确连接。我尝试了Chris的建议,但没有解决我的问题。还有其他建议吗?Chris,谢谢你的编辑,但是你能详细说明一下吗:“这个更改不需要知道DATEDIFF部分,因为它可以被旧的Sent_Views+Sent_Winks之和除以,再乘以新的。”。也许我遗漏了什么,但是在不知道DATEDIFF(现在(),DateRegistered)的情况下,如何更新分数呢?也许您的意思是,稍后将使用cron作业重新计算分数,该作业将考虑DATEDIFF(现在(),DateRegistered)?@user1009456我的意思是,每次用户的视图或眼色更改时,您只需将现有分数乘以(new_sum/old_sum)。分数的DATEDIFF部分仅每24小时计算一次。如果你需要更多的澄清,请告诉我。
SELECT
   UserId, score  
FROM
  statistics_user 
ORDER BY score DESC