这个记录/扇出逻辑是如何在MySQL的查询计划器中为“无统计”情况得出的?

时间:2017-08-06 03:50:56

标签: mysql

在MySQL Server 5.7源代码中,在查询计划程序中使用公式records = (x * (b-a) + a*c-b)/(c-1)来计算密钥分发统计信息不可用时的记录数。

这个公式来自何处,它是如何得出的,或者为什么这个特定公式是正在使用的公式?它是否有一个既定的理论基础,如果有,它的基础是什么?

https://github.com/mysql/mysql-server/blob/5.7/sql/sql_planner.cc#L529

          Assume that the first key part matches 1% of the file
          and that the whole key matches 10 (duplicates) or 1
          (unique) records.
          Assume also that more key matches proportionally more
          records
          This gives the formula:
          records = (x * (b-a) + a*c-b)/(c-1)
          b = records matched by whole key
          a = records matched by first key part (1% of all records?)
          c = number of key parts in key
          x = used key parts (1 <= x <= c)

1 个答案:

答案 0 :(得分:0)

如果您完全没有关于问题的数据,则不得不进行估算。

该公式的一般形式在评论中解释:

  • 如果我们只使用一个多列索引(x列)的一个键列(c),我们会得到a行(占总行数的1%)。因此对于x=1,根据定义,结果为a
  • 如果我们知道多列索引的每个键列的值,我们得到每个整个键的行数b);因此对于x=c,我们根据定义获得b行( 1 10 )。
  • 介于两者之间(如果我们使用超过1个键列的键值,但不是全部),对于每个额外的已知键值,我们可以排除一些额外的行:我们有a-b行不属于这种情况我们知道完整键(可能有b行),根据定义,它们应按比例排除在可用键列的比例((x-1)/(c-1))之外。
  • -1中的(x-1)/(c-1)只是一个转变(您可以使用不同的变量名称),因为我们只需要计算其他列,但是{{1 }和c是包含第一列的计数。 (在时间序列中,您可以调用第一列 x的参数,t=0完全相同。

总而言之,我们得到-1a - (a-b) * (x-1)/(c-1)代表第一个键列减去我们按比例排除的行数。这是(如果你稍微改变那个表达式)恰好给出的公式。快速完整性检查:对于ax=1),第二项是 0 ,我们得到x-1=0,由第一个条件定义;对于a,我们得到第二个条件定义的x=c

使用这些假设来制作这个问题并不是没有道理的,但你可能会找到一个有意义的不同公式。认为它更好是一项艰巨的任务。

然后是选择值的问题(在这种情况下为a-(a-b)=bb=10)。你显然可以选择任何价值。为了做到这一点,除了直觉之外没有任何可靠的数据,有一个名为Fermi estimate的概念:

  

估算技术以物理学家恩里科·费米(Enrico Fermi)的名字命名,因为他以很少或没有做出良好近似计算的能力而闻名。   实际数据。

您基本上只为输入参数选择了Magnite(1,1000000,1 / 100)的顺序,您的结果会得到合理的数量级。

那么你期望一个非唯一键覆盖多少行?它超过1,否则你会把它变成一个独特的键,但更像是2,10或100? 10可能是一个很好的猜测(它涵盖了该估计中大约3到30的值)。因此,虽然这个数字可能来自于一项关于密钥分配的2年全球调查,但10个权力的估计值通常是以这样的方式得出的。如果您想绝对确定,请询问开发人员。

此类主题的obligatory xkcdWhat-if? Paint the Earth