我的问题是,我有一个mysql查询运行得非常快(0.3秒),尽管它有大量的左联接和联接列上的一些条件,但当我再添加一个条件时,查询需要花费180秒以上!我理解,条件意味着执行计划必须调整,首先拉出所有潜在的记录,然后在循环中应用条件,但对我来说奇怪的是,没有附加条件的快速查询只返回16行,即使只是用外部查询上的条件包装查询也要花费大量的时间,而您认为它只会添加一个通过16行的附加循环。
如果重要的话,这就是使用Amazon Aurora无服务器,它应该与MySQL5.7一致
下面是查询的样子。可以看到附加条件被注释掉了。(数据库本身的通用表结构目前无法更改,因此请不要建议进行完整的数据库重组)
select
e1.entityId as _id,
v1.Value,
v2.Value
v3.Value,
v4.Value,
v5.Value,
v6.Value,
v7.Value,
v8.Value,
v9.Value,
v10.Value,
v11.Value,
v12.Value
from entity e1
left join val as v1 on (v1.entityId = e1.entityId and v1.attributeId = 1189)
left join val as v2 on (v2.entityId = e1.entityId and v2.attributeId = 1190)
left join entity as e2 on e2.entityId = (select entityId from entity where code = v1.Value and type = 88 limit 1)
left join val as v3 on (v3.entityId = e2.entityId and v3.attributeId = 507)
left join val as v4 on (v4.entityId = e2.entityId and v4.attributeId = 522)
left join val as v5 on (v5.entityId = e2.entityId and v5.attributeId = 558)
left join val as v6 on (v6.entityId = e2.entityId and v6.attributeId = 516)
left join val as v7 on (v7.entityId = e2.entityId and v7.attributeId = 518)
left join val as v8 on (v8.entityId = e2.entityId and v8.attributeId = 1384)
left join val as v9 on (v9.entityId = e2.entityId and v9.attributeId = 659)
left join val as v10 on (v10.entityId = e2.entityId and v10.attributeId = 519)
left join val as v11 on (v11.entityId = e2.entityId and v11.attributeId = 1614)
left join entity as e3 on e3.entityId = (select entityId from entity where code = v9.Value and type = 97 limit 1)
left join val as v12 on (v12.entityId = e3.entityId and v12.attributeId = 661)
where e1.type = 154
and v2.Value = 'foo'
and v5.Value = 'bar'
and v10.Value = 'foo2'
-- and v11`.Value = 'bar2'
order by v3.Value asc;
把它包在这样的东西里还需要很长时间...
select *
from (
<query from above>
) sub
where sub.v11 = 'bar2';
我将在“实体”表上摆弄索引来改进执行计划,不管这可能会有什么帮助...但是,有人能解释一下这里发生了什么,我应该在执行计划中看到什么,这会显示出如此糟糕的表现吗?为什么将快速查询包装在子查询中,使外部查询只能循环16行需要很长的时间呢?
编辑:我注意到在慢速查询中,最左边的执行使用的是“68e9145e-43eb-4581-9727-4212be41bef5”(v11)的非唯一键查找(在val.entityId上),而不是其他执行使用的唯一键查找(在entityId和attributeId上的复合索引)。我想这可能是问题的一部分,但为什么它不能像其他地方一样使用综合指数呢?
PS:现在,由于我们知道结果集很小,我们将在nodeJS服务器中的结果集上使用过滤器实现最后一个条件服务器端。
下面是“show CREATE TABLE entity”和“show CREATE TABLE val”的结果。
CREATE TABLE `entity` (
`entityId` int(11) NOT NULL AUTO_INCREMENT,
`UID` varchar(64) NOT NULL,
`type` int(11) NOT NULL,
`code` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
PRIMARY KEY (`entityId`),
UNIQUE KEY `UID` (`UID`),
KEY `IX_Entity_Type` (`type`),
CONSTRAINT `FK_Entities_Types` FOREIGN KEY (`type`) REFERENCES `entityTypes` (`typeId`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=296138 DEFAULT CHARSET=latin1
CREATE TABLE `val` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`UID` varchar(64) NOT NULL,
`attributeId` int(11) NOT NULL,
`entityId` int(11) NOT NULL,
`Value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
PRIMARY KEY (`id`),
UNIQUE KEY `UID` (`UID`),
UNIQUE KEY `idx_val_entityId_attributeId` (`entityId`,`attributeId`),
KEY `IX_val_attributeId` (`attributeId`),
KEY `IX_val_entityId` (`entityId`)
) ENGINE=InnoDB AUTO_INCREMENT=2325375 DEFAULT CHARSET=latin1
请提供show CREATE table
。
我希望看到这些综合指数:
`val`: (entityId, attributeId) -- order is not critical
唉,因为code
是longtext
,所以对于entity
:index(type,code,entityId)
是不可能的。因此,这将不是很有效:
SELECT entityId
from entity
where code = v9.Value
and type = 97
limit 1
我看到limit
有一个order by
--您关心您得到的是哪个值吗?
也许这样写更好
WHERE EXISTS ( SELECT 1 FROM entity
WHERE entityID = e3.entityID
AND code = v9.Value
AND type = 97 )
(您确定E3
和V9
的混合使用吗?)
正在包装...
这将强制左联接
变为联接
。并且它摆脱了当时内部的顺序
。
那么优化器可能会决定最好从68E9145E-43EB-4581-9727-4212BE41BEF5
开始,我将其称为VAL AS V11
:
JOIN val AS v11 ON (v11.entityId = e2.id
and v11.attributeId = 1614)
AND v11.Value = 'bar2')
如果这是一个EAV表,那么它所做的就是验证[,1514]是否具有值'bar2'。这似乎不是一个明智的测试。
除了我以前的建议。
我更喜欢解释选择...
。
EAV
假设val
是一个传统的EAV表,这可能会好得多:
CREATE TABLE `val` (
`attributeId` int(11) NOT NULL,
`entityId` int(11) NOT NULL,
`Value` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
PRIMARY KEY(`entityId`,`attributeId`),
KEY `IX_val_attributeId` (`attributeId`),
) ENGINE=InnoDB AUTO_INCREMENT=2325375 DEFAULT CHARSET=latin1
这两个ID没有实际用途(除非我遗漏了什么)。如果你因为一个框架而被迫使用它们,那是不幸的。将(entityId,attributeId)提升为PK使获取value
的速度更快。
没有任何有用的方法可以在任何索引中包含longtext
,因此我前面的一些建议需要更改。
我有5个SQL表 存储 工作人员 部门 SOLD_Items staff_rating 我创建了一个视图,将这四个表连接在一起。最后一个表(staff_rating),我希望在接近项目被出售的时间(sold_items.date)获得视图行的rating列。我尝试了以下SQL查询,这些查询工作正常,但存在性能问题。 SQL查询1 SQL查询2 SQL查询%2比SQL查询%1快。但这两种方法都存在性
问题内容: 有人愿意帮助我吗?在具有10000行的MEMORY表上,以下查询大约需要18秒。如果我没有“ where”约束,则只需不到一分钟的时间。我已经打开查询缓存以及将其作为准备好的语句来尝试。有什么我可以做的吗?索引还是什么? 问题答案: 我认为这将为您提供所需的信息,而不管您关注的滚动日期范围…我已经通过创建带有两个标识列的自己的“发票”表进行了测试。使用@mySQL变量实际上非常简单,可
主要内容:单一条件的查询语句,多条件的查询语句在 MySQL 中,如果需要有条件的从数据表中查询数据,可以使用 WHERE 关键字来指定查询条件。 使用 WHERE 关键字的语法格式如下: WHERE 查询条件 查询条件可以是: 带比较运算符和逻辑运算符的查询条件 带 BETWEEN AND 关键字的查询条件 带 IS NULL 关键字的查询条件 带 IN 关键字的查询条件 带 LIKE 关键字的查询条件 单一条件的查询语句 单一条件指的是在
1)使用的第一个查询...大约用了23秒 目前我修改了查询..这需要大约9秒 我不确定要做的表演是什么?我希望这个查询是快速的..我尝试索引rid和id,但这仍然使查询变得更糟。 下面是表格的详细信息 mza_movie_upload MZA_Movie_Statics
我在术语查询中要求弹性搜索中的嵌套字段,其中嵌套字段值应与术语查询中提供的值的数量完全匹配。例如,考虑下面的查询,在这里我们对名为类型的嵌套字段进行查询。 GET资产/_search 索引映射 样本文件: 上述查询应返回字段类型正好有2个值的文档,即“VOD”
查询条件: {a:1,b:undefined}, {a:1,b:null}, mongodb查询,会忽略上述b字段吗?