当前位置: 首页 > 知识库问答 >
问题:

mysql - 为什么这个sql左连接这么慢?

能钟展
2024-07-26
SELECT
    ad.id,
    d.device_id,
    d.d_id AS variable_id,
    d.d_name,
    d.oper_type,
    d.d_type,
    d.d_decimal AS 'decimal',
    d.data_prot_param,
    ad.tag,
    ad.modbus_reg_addr,
    ad.modbus_area 
FROM
    box_api_data ad
    LEFT JOIN box_data_info d ON d.d_id = ad.variable_id 
WHERE
    ad.unique_code = '7000224061716030893' 
    AND ad.topic_id = 572137887207493 
    AND d.unique_code = '7000224061716030893'

这个sql查询要6s多,但是我两张表数据量都不是很大呀。box_api_data目前40000条,box_data_info目前10006条。基本都是比较少的,这么个数据量连接查询居然干到了6s,是我sql有问题吗?目前两张表都没有索引。

CREATE TABLE `box_data_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `unique_code` varchar(50) NOT NULL COMMENT '所属编号',
  `device_id` int(11) NOT NULL COMMENT '所属设备',
  `d_id` int(11) NOT NULL COMMENT '变量标识',
  `d_name` varchar(128) NOT NULL COMMENT '变量名称',
  `oper_type` int(11) NOT NULL COMMENT '操作类型(0:只读,1:只写,2:读写)',
  `d_type` int(11) NOT NULL COMMENT '数据类型',
  `unit` varchar(30) DEFAULT NULL COMMENT '变量单位',
  `d_decimal` int(11) DEFAULT '0' COMMENT '小数位数',
  `min_range` varchar(20) DEFAULT NULL COMMENT '最小量程',
  `max_range` varchar(20) DEFAULT NULL COMMENT '最大量程',
  `r_formula` varchar(156) DEFAULT NULL COMMENT '读公式',
  `w_formula` varchar(156) DEFAULT NULL COMMENT '写公式',
  `d_status` int(11) DEFAULT NULL COMMENT '变量状态 0:离线,1:在线',
  `is_store` int(11) DEFAULT '0' COMMENT '是否存储',
  `data_prot_param` varchar(1000) DEFAULT NULL COMMENT '特殊配置',
  `is_custom` int(11) NOT NULL DEFAULT '0' COMMENT '是否是自定义变量(0:不是,1:是)',
  `trans_modbus_param` varchar(1000) DEFAULT NULL COMMENT '转换Modbus协议参数',
  `remark` varchar(256) DEFAULT NULL COMMENT '备注',
  `data_index` int(11) DEFAULT NULL COMMENT '数据索引',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=848295 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='点表';

CREATE TABLE `box_api_data` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `topic_id` bigint(20) DEFAULT NULL COMMENT '主题id',
  `variable_id` int(11) DEFAULT NULL COMMENT '数据标识',
  `device_id` int(11) DEFAULT NULL COMMENT '设备id',
  `tag` varchar(127) DEFAULT NULL COMMENT '数据标签',
  `modbus_area` varchar(10) DEFAULT NULL COMMENT 'modebus区域',
  `modbus_reg_addr` int(11) DEFAULT NULL COMMENT 'modebus寄存器地址',
  `modbus_data_type` int(11) DEFAULT NULL COMMENT 'modbus在寄存器中的实际数据类型',
  `opcua_data_con` mediumtext COMMENT 'opcua特殊数据',
  `type` char(10) DEFAULT 'variable' COMMENT '类型(variable:变量,rule:规则)',
  `unique_code` varchar(50) NOT NULL COMMENT '网关编号',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2452557 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='接口变量表';

image.png

共有1个答案

马峻
2024-07-26

你这一个索引都没加,肯定慢了,另外你这如果不限制取回的行数,并且时 left join,那左表(主表)是会全表扫描的,在一定程度上也会慢。

# 添加索引
alter table box_data_info add index idx_unique_code_d_id (unique_code, d_id);
alter table box_api_data add index idx_topic_id_variable_id_unique_code (topic_id, variable_id, unique_code);


# 改写 SQL,如果你查询的两个表的 unique_code 始终是相匹配的,可以直接在关联的时候就筛选掉副表的数据

SELECT
    ad.id,
    d.device_id,
    d.d_id AS variable_id,
    d.d_name,
    d.oper_type,
    d.d_type,
    d.d_decimal AS 'decimal',
    d.data_prot_param,
    ad.tag,
    ad.modbus_reg_addr,
    ad.modbus_area 
FROM
    box_api_data ad
    LEFT JOIN box_data_info d ON d.d_id = ad.variable_id and ad.unique_code = d.unique_code
WHERE
    ad.unique_code = '7000224061716030893' 
    AND ad.topic_id = 572137887207493 

box_data_info 这个表的索引,你要看根据你的实际情况可以调整一下这两个字段的顺序,因为这里都在关联条件里面,应该是可以走到并覆盖的。

 类似资料:
  • 问题内容: 我使用JDBC连接到MySQL。在时,一切正常。 但是,当我将应用程序移动到Intranet中的另一台计算机上并用于连接到MySQL数据库时,大约需要1分钟才能成功连接到MySQL。这是怎么回事? 问题答案: 好吧,这可能是DNS问题。您可以通过从配置文件中的选项开始禁用DNS主机名查找。 在这里阅读更多详细信息:http : //dev.mysql.com/doc/refman/5.

  • 问题内容: 下面是我的SQL代码: 表已正确索引。可以重写此代码以获得更好的性能吗? 问题答案: 您也可以尝试EXISTS:

  • 问题内容: 我正在使用较大的随机数作为密钥(来自另一个系统)。在相当小的表(如几百万行)上进行插入和更新所花费的时间比我认为合理的长得多。 我已经提炼了一个非常简单的测试来说明。在测试表中,我尝试使其尽可能简单。我的真实代码没有如此简单的布局,并具有关系和附加索引等。但是,更简单的设置将显示等效的性能。 结果如下: 在MyISAM中插入1M行需要6秒钟;进入InnoDB需要 3433秒 ! 我究竟

  • 问题内容: 这是所有编程语言所共有的吗?在进行多次打印后再执行println似乎更快,但是将所有内容移动到字符串中并仅进行打印似乎最快。为什么? 编辑:例如,Java可以在不到一秒钟的时间内找到所有高达100万的质数- 但要进行打印,然后在自己的println中将它们全部输出可能需要几分钟!最多可打印100亿小时! 例如: 问题答案: 速度并不慢,而是由主机操作系统提供的与控制台连接的基础。 您可

  • 问题内容: 我对此感到困惑 现在让我们来看看numpy: 神圣的CPU周期蝙蝠侠! 使用改进,但恕我直言仍然不够 numpy.version.version =‘1.5.1’ 如果您想知道在第一个示例中是否跳过了列表创建以进行优化,则不是: 问题答案: Numpy已针对大量数据进行了优化。给它一个很小的3长度数组,毫不奇怪,它的性能很差。 考虑单独的测试 输出是 似乎是数组的归零一直花费在nump

  • 问题内容: Magento通常这么慢吗? 这是我的第一次使用体验,管理面板只需花一些时间即可加载和保存更改。这是带有测试数据的默认安装。 托管该服务器的服务器可超快地服务于其他非Magento站点。Magento使它如此缓慢的PHP代码有什么用,该如何解决? 问题答案: 我只是切身参与优化Magento的性能,但这是系统速度如此缓慢的一些原因 Magento的某些部分使用在MySQL之上实现的EA

  • 问题内容: 在有人质疑使用的事实之前,我先说一下,出于内存和性能的原因,我需要在特定的应用程序中使用它。[1] 因此,到目前为止,我一直使用并假定这是最有效的方法。但是,自古以来我就注意到它是软件的瓶颈。[2] 然后,就在最近,我试图用一个巨大的映射替换,在该映射中放置/获取字符串,以便每次获得唯一的实例。我以为这会慢一些…但是事实恰恰相反!它快得多了!通过推送/轮询地图(实现完全相同)来替换,可

  • 对于特定的任务,我需要在可变数组中进行大量快速、单独的写操作。为了检查性能,我使用了以下测试: