我目前正在研究查询优化,我正在尝试计算其中包含依赖查询的查询的成本。
查询是:
select
U.userName, email, yearOfBirth, countryName
from
tblUser U
inner join
tblCountry C on U.countryNo = C.countryNo
left join
tblList L on U.userName = L.userName
where
noOfPoints = 1000
and yearOfBirth = 1975
and listNo is null
and not exists (select count(*)
from tblseek S
where S.userName = U.userName
having count(serialNo) > 3)
现在有些数据:
首先是表格及其连接:
tblCountry:Nr = 19,Fr = 67且Br = 1
tblUser:Nr = 1,881,923,Fr = 11,Br = 171,084
tblList:Nr = 4,667,166,Fr = 62,Br = 75,277
tblSeek:Nr = 8,530,865,Fr = 13,Br = 656,221
用户之间的分配就宝藏的查找量而言:
0查找:10%的用户
1次查询:11%的用户
2次查询:19%的用户
3及以上:60%的用户
就每个用户的列表数量而言,用户之间的分配是:
0列表:30%的用户
1-3列表:34%的用户
4-6列出:36%的用户
众所周知,所有系统中的最大点数为5200,并且在用户之间均匀分布。
据了解,年龄最大的用户年龄为16岁,年龄最大的是57岁,所有用户的年龄均匀分布。
块大小为:2048位
为查询分配的内存量为:100块
每个表都按主键排序,如果有多个字段,则按照表中的外观顺序排序。
现在,我想要计算的是什么:
我试图在外部查询中进行连接之前确定运行依赖查询的成本,因此将tblUser加载到内存并执行内部查询,然后完成其他连接。
我的问题:我发现为了做到这一点,我需要以171,084个块为代价将tblUser加载到内存中,并且还需要以656,221个块为代价加载tblSeek,我无法确定是如何以及在何处执行" Where"因为您可能会注意到该子句中的大多数条件都与tblUser的属性有关(除了列表条件)。
我设法得出一个估计(我不确定这是正确的,请纠正我,如果我错了)有多少记录会回答" points = 1000"在统一的转移知识(其361条记录)下,并且也与#34; yearOfBirth = 1975"(45,900条记录)相同。我是通过将tblUser的Nr分别与均匀转移已知的数字区域分开来实现的。
我怎么能想出一种方法将它们组合成一个数字,显示有多少记录会在所有条件混合在一起(包括依赖查询)。
如果你能引导我一点,我将非常感激。
谢谢,
汤姆
答案 0 :(得分:0)
使用EXPLAIN FORMAT=JSON SELECT ...
进一步了解查询的执行方式。
使用它来获得努力的一些“行数”:
FLUSH STATUS;
SELECT ...
SHOW SESSIONS STATUS LIKE 'Handler%';
指标的影响。 (我不知道你已经拥有什么,因为你没有提供SHOW CREATE TABLE
。)
U: INDEX(yearOfBirth, noOfPoints)
EXISTS(...)
通常简称为EXISTS ( SELECT * FROM ... )
;不需要COUNT(*)
。我不明白EXISTS
的目的。也许这会检查tblseek
中的行数:
AND ( SELECT COUNT(*) FROM tblseek WHERE userName = U.userName ) <= 3
您可能希望INDEX(userName, serialNo)
按此顺序。这是一个“覆盖”索引,以便子查询可以完全在索引中执行。 EXPLAIN
将通过“使用索引”来表示。
该子查询总共将触及tblseek(或其索引)中的每一行。实际上,每次扫描都会超过一次。因此,触摸的行数可能是N + M,其中N是tblseek
中的行数,M是userName
中tblseek
的不同值的数量。如果没有该索引,行数将会高很多。