在赞成票和反对票之间建立平衡很慢,而且无法按预期工作

Creating Balance between up- and downvotes is slow and does not work as expected

我有一个 table 文章投票。

CREATE TABLE `articlevote` (
  `id` int NOT NULL AUTO_INCREMENT,
  `articleid` int NOT NULL,
  `ipaddress` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `vote` int NOT NULL,
  PRIMARY KEY (`id`,`articleid`,`ipaddress`),
  UNIQUE KEY `UNIQUEVOTE` (`articleid`,`ipaddress`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=149235 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

对于这个最小的例子,我插入了 3 篇文章投票

insert into articlevote (id,articleid, ipaddress, vote) values (1,1,"1.2.3.4",1),(2,2,"1.2.3.4",1),(3,1,"1.2.3.5",-1);

专栏投票:1 = 赞成票,-1 = 反对票
ipaddress 应该可以防止双重投票。

我有一个查询要给我点赞最多的文章

SELECT v.articleid, count(v.vote) as votes FROM articlevote v 
        WHERE v.vote > 0 
        GROUP BY v.articleid 
        ORDER BY votes DESC;

但现在我需要获得一份考虑到赞成票和反对票的最受欢迎文章的列表。

我试过了

SELECT v.articleid, sum(v.vote) as votes FROM articlevote v 
        GROUP BY v.articleid 
        ORDER BY votes DESC;

我希望第 2 条以 1 票位居榜首,第 1 条以 0 票位居第二。 但是我得到第 1 条和第 1 条的总票数。 在大型数据集上,使用 sum 聚合的查询比使用 count 聚合的查询要慢得多。

如何在高性能查询中同时获得预期结果?

使用最新版本的 mysql 8 你没有那个问题,也许是一个错误,u 已经修复了

CREATE TABLE `articlevote` (
  `id` int NOT NULL AUTO_INCREMENT,
  `articleid` int NOT NULL,
  `ipaddress` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `vote` int NOT NULL,
  PRIMARY KEY (`id`,`articleid`,`ipaddress`),
  UNIQUE KEY `UNIQUEVOTE` (`articleid`,`ipaddress`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=149235 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
insert into articlevote (id,articleid, ipaddress, vote) values (1,1,"1.2.3.4",1)
,(2,2,"1.2.3.4",1)
,(3,1,"1.2.3.5",-1);
SELECT v.articleid, sum(v.vote) as votes FROM articlevote v 
        GROUP BY v.articleid 
        ORDER BY votes DESC;
articleid | votes
--------: | ----:
        2 |     1
        1 |     0

db<>fiddle here

  • 干掉id;它似乎完全没用。另外它会影响性能。

  • UNIQUE升级为PRIMARY

  • 不要在 +1 或 -1 的值上浪费 4 个字节;而不是 INT 使用 TINYINT (1 字节)。

  • 大型 ISP 中的用户共享 IP 地址 -- 两个用户可能拥有相同的 IP(在不同时间),或者不经常使用的用户可能获得不同的 IP。

  • 您处理的是 IPv4,而不是 IPv6。

  • COUNT(vote) 检查 vote 在总数中包含“1”或排除它之前是否为 NOT NULL。它没有看到 vote.

    的符号
      CREATE TABLE `articlevote` (
        `articleid` int NOT NULL,
        `ipaddress` varchar(15) CHARACTER SET ascii NOT NULL,
        `vote` TINYINT NOT NULL,
        PRIMARY KEY (`articleid`,`ipaddress`) USING BTREE
      ) ENGINE=InnoDB;