Py学习  »  DATABASE

使用超过10万条记录优化MySQL查询

Rafael Dorado • 3 年前 • 1680 次点击  

我希望你能帮我优化这个查询。

SELECT  carrier,
        SUM(views) AS views,
        SUM(views-1) AS repeated,
        SUM(views >= 1) AS unique_views,
        COUNT(1) AS total
    FROM  stats s1
    WHERE  id_link = 39
      AND  EXISTS (
        SELECT  *
            FROM  stats s2
            where  id_link = 39
              AND  s2.carrier = s1.carrier
            LIMIT  1, 1 )
    GROUP BY  carrier
    HAVING  COUNT(1) >= 1
    LIMIT  1,1
 UNION 
 SELECT  'TOTAL' AS carrier,
        SUM(views) AS views,
        SUM(views-1) AS repeated,
        SUM(views >= 1) AS unique_views,
        COUNT(1) AS total
    FROM  stats s4
    WHERE  id_link = 39
      AND  EXISTS (
        SELECT  *
            FROM  stats s3
            where  s3.carrier = s4.carrier
            LIMIT  1, 1 )

数据库:

CREATE TABLE `stats` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_link` int(11) NOT NULL,
`country` varchar(100) NOT NULL,
`ip` varchar(100) NOT NULL,
`views` varchar(1000) NOT NULL,
`asn` varchar(1000) NOT NULL,
`carrier` varchar(1000) NOT NULL,
`type` varchar(1000) NOT NULL,
`device` varchar(1000) NOT NULL,
`browser` varchar(1000) NOT NULL,
`fecha` datetime NOT NULL,
`referrer` varchar(2000) NOT NULL,
PRIMARY KEY (`id`),
KEY `id_link` (`id_link`),
CONSTRAINT `stats_ibfk_1` FOREIGN KEY (`id_link`) REFERENCES `campaigns` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=614606 DEFAULT CHARSET=utf8

我正在创建一个网络流量跟踪器。 我有一张叫做“统计”的桌子,放在那里;视图、ASN、IP、浏览器、设备等,其中包括“运营商”,即互联网服务提供商

我想看看每个运营商有多少次访问,账户重复了不止一次,有多少次独特的访问。

我的代码已经实现了我想要的功能,但它只在记录很少的情况下工作,现在我有超过10万条记录,服务器崩溃,它无法加载查询,我甚至必须重新启动apache。

这里我只留下一个说明性的图片

enter image description here

有没有办法加快这个查询的速度?

提前感谢您的评论和帮助。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/130501
文章 [ 2 ]  |  最新文章 3 年前
Rick James
Reply   •   1 楼
Rick James    4 年前

** views 就好像它是一个数字一样使用。如果是这样,不要使用 VARCHAR 建议 INT UNSIGNED (最高可达40亿美元)。

**使用合理的限制,而不是 varchar(1000) .

**越小越好。所以规范化经常重复的列。 carrier 有9个不同的值吗?A. SMALLINT UNSIGNED 只需要2个字节,并且有足够的空间来处理大量的载波。大部分时间也是如此 瓦查尔(1000) .

**建议使用标准的双字母“国家/地区代码”( CHAR(2) )而不是 country(100) --在美国、英国、法国。。。

**特别是为了加快查询速度

KEY `id_link` (`id_link`),

KEY `id_link` (`id_link`, carrier),

**研究使用 WITH ROLLUP GROUP BY 所以你不需要 UNION 其次 SELECT

**考虑建立和维护一个每日汇总表的“汇总表”。查询这个表将比查询当前的原始(“事实”)表快得多。更多信息: http://mysql.rjweb.org/doc.php/summarytables (这是Shubham在评论中提到的内容的扩展。)

Shubham Dange
Reply   •   2 楼
Shubham Dange    4 年前

您可以使用Mysql偏移量和限制来实现它

您可以尝试使用ajax,首先加载1500条记录,滚动或单击next load next 1500 records,使用datatables,它有内部分页+additinal next按钮以获得更多结果, 例如 第一页偏移量=0,限制=1500 第二页偏移量=1500,限制为1500。。等等