Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1ermuW-0002H6-Sy for pgsql-hackers@arkaria.postgresql.org; Fri, 02 Mar 2018 15:47:53 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1ermuV-0008L0-KK for pgsql-hackers@arkaria.postgresql.org; Fri, 02 Mar 2018 15:47:51 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1ermuV-0008Kn-8k for pgsql-hackers@lists.postgresql.org; Fri, 02 Mar 2018 15:47:51 +0000 Received: from mail.postgrespro.ru ([93.174.131.138]) by magus.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1ermuR-0004sy-IB for pgsql-hackers@lists.postgresql.org; Fri, 02 Mar 2018 15:47:50 +0000 Received: from localhost (localhost [127.0.0.1]) by mail.postgrespro.ru (Postfix) with ESMTP id 3112D21CA178; Fri, 2 Mar 2018 18:47:45 +0300 (MSK) X-Virus-Scanned: Debian amavisd-new at postgrespro.ru X-Spam-Flag: NO X-Spam-Score: 0 X-Spam-Level: X-Spam-Status: No, score=x tagged_above=-99 required=4 WHITELISTED tests=[] autolearn=unavailable Received: from [192.168.27.132] (gw.postgrespro.ru [93.174.131.141]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client did not present a certificate) by mail.postgrespro.ru (Postfix) with ESMTPSA id D98DC21CA177; Fri, 2 Mar 2018 18:47:44 +0300 (MSK) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=postgrespro.ru; s=mail; t=1520005665; bh=Ww1bUnr1+2degMddfww0CZZLOySgup6OnZASsHOXtkc=; h=Subject:To:Cc:References:From:Date:In-Reply-To; b=VvXWgE2zJ7QZXYCMMpulTiLWyDEnJBYlPO2SrTjY0sgvxCEoYeELDJzWgx9BvHOTE 3ZugKJ/3eBdpx2R3ENVqxeHxu71d55Abx8q1hw10e3PPoB02lolM9BHLMi2ptQ5mbr xbmm62J/+lRR4IKxqg0eqRIEakwY6zeBEcD1qB1o= Subject: Re: [patch] BUG #15005: ANALYZE can make pg_class.reltuples inaccurate. To: Tom Lane Cc: David Gould , pgsql-hackers@lists.postgresql.org, Alina Alexeeva , Ullas Lakkur Raghavendra References: <20180117164916.3fdcf2e9@engels> <20180228192337.67cc3f99@engels> <4988c54a-1709-a978-9a43-65f8a1e09e94@postgrespro.ru> <18522.1519916974@sss.pgh.pa.us> <1386effe-0e6d-fd5a-6f0d-f294e4ef2dda@postgrespro.ru> <3240.1519948160@sss.pgh.pa.us> From: Alexander Kuzmenkov Message-ID: <101dd073-1cb7-b471-7eeb-aa9ee928a1c9@postgrespro.ru> Date: Fri, 2 Mar 2018 18:47:44 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.0 MIME-Version: 1.0 In-Reply-To: <3240.1519948160@sss.pgh.pa.us> Content-Type: multipart/mixed; boundary="------------0E94144F7479196F45AB2851" Content-Language: en-US List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk This is a multi-part message in MIME format. --------------0E94144F7479196F45AB2851 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit On 02.03.2018 02:49, Tom Lane wrote: > I looked at this and don't think it really answers the question. What > happens is that, precisely because we only slowly adapt our estimate of > density towards the new measurement, we will have an overestimate of > density if the true density is decreasing (even if the new measurement is > spot-on), and that corresponds exactly to an overestimate of reltuples. > No surprise there. The question is why it fails to converge to reality > over time. The calculation I made for the first step applies to the next steps too, with minor differences. So, the estimate increases at each step. Just out of interest, I plotted the reltuples for 60 steps, and it doesn't look like it's going to converge anytime soon (see attached). Looking at the formula, this overshoot term is created when we multiply the old density by the new number of pages. I'm not sure how to fix this. I think we could average the number of tuples, not the densities. The attached patch demonstrates what I mean. -- Alexander Kuzmenkov Postgres Professional: http://www.postgrespro.com The Russian Postgres Company --------------0E94144F7479196F45AB2851 Content-Type: image/png; name="analyze.png" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="analyze.png" iVBORw0KGgoAAAANSUhEUgAABAAAAAMACAMAAACNZOU/AAABNVBMVEX///+/v78/Pz8fHx9f X1+fn5/f39++vr6g/yB8/0DNwLDB/8Ggts3w//DNt57//8D//4D/wMD/oHD/oGD/oED/gECA gACAYP+AYMCAQICAQBSAFBSAFABVay+QUEDdoN2UANPugu7/pQCggCD19dy4hgu9t2vw5ozp lnr6gHL/RQDwgID/f1D/FJMAztH/AP8A//+HzusAAM0AAIAZGXAAAIsAAP8ui1ciiyIA/38A ZAAA/wD/1wCv7u7/tsHu3YLg///wVfCt2OaQ7pDwMjL////l5eXMzMzAwMCzs7OZmZl/f39m ZmZNTU0zMzMaGhoAAABA4ND//wClKip//9T/gP9AgACLAAAwYIDAgP8AgED/wCBBaeHIyADA QAAA7u7AAP8AgP8AwAD/AACgoKAAAAD///+OADecAAAAAXRSTlMAQObYZgAAAAlwSFlzAAAO xAAADsQBlSsOGwAAIABJREFUeJztnQu2qygQRVtUxnHn4zQemf8Q2r9owMQIyGfvtdJ9E5OU 9SLHqqLE/14AUCz/Pb0DAPAcCABAwSAAAAWDAAAUDAIAUDAIAEDBIAAABYMAABQMAgBQMAgA QMEgAAAFgwAAFAwCAFAwCABAwSAAAAUTrQCohad3BCBjohcA8fSOAGRMtAIwIVT79C4AZEzc AiDJAAB8ErcAdKp5ehcAcsavAHSiVnVTmTbJtql35/dW9An/IeCvlfGzAOAGnwIg65NC/nGL MNT8KlV73D0A8CgA/fgXlexP9cZCft20eobfqbo/+7e16rT3NLtnAOAajwIgPibwmwD0WjAG +5VSUt8uXwDgD38CID/H75sAtItYNNq8X0sTAIBf/AlAt4/fG1XL8Y8+M1gig00A1nHfamGD IAMA8Is/ARCqqsZJALk8F7v/v3QBqNX8Li1ukGQAUBJ/Txj1JwC16uZJgGkqbz7zr5HASxeA 9S9NADoyACiIv78nFMCfAAxDvz/7y2Y5kVeqj/NbpU3tGwRgFxXQBgzlkKEALDH/nNb3g79T +qg+FwCAgvj7e0QBfKYA87l+a+cZcgK9rneeAgCUw9/fMwrgVQDk+MfW79MnAfNrE+dFQDsK AIxcHab+BKB5F4Ba1bvC3odpQCvhs4TgFnExB4vfG/z7cxMCRCQA7VsK0Cghd72+HxqBrHDo 5GARFzf+/hwpQEQCILci4DTm2yEkqPQq4KdWYBscOjlYxMWNHAVgKPnp04ByGvqdNsQ/XQxk g0MnB4u4ODAO+L8/VwoQkwAMVYCRKRNYOoCbKTA4li1MlwPb4NDJwSIuvubJ/78/ZwoQlQC8 Wq0VuFnL+5MSvNUtTQuCWODQycEiLr5yFwBfcOjkYBEX34b+fQVAAACSwX33DwLgh3/ZG8TF BwwiAL+BAORgERdddf9oIAAAieBs8l8DAQBIBATgV0gBcrBYrovTeHfX/aOBAPghlkMnJ4vF ujiNd4eT/xoIAEDkIAB3QQAgXabx7rL7RwMB8EMkwWNWFgt10f3cvw4C4IcoDp3MLBbqIgJw H1IASBUPzT86CABAxPiY+9dBAPwQRfCYmcUiXUQAXIAA5GCxMBcdL/1jAQEAiJE/xyt/WEAA AGIEAXAIKUAOFoty8a3vx5MCIAB+YHRkYPBBF/1O/msgAADxgQA4BQGApPDc/aOBAPiB+DgD g4+56HvyXwMB8AOjIwODCIABBADAFx6X/rGAAADEwp/HlT8sIAB+ID7OwGBwiwiAJxCAHCxm 7+I03gN0/2ggAABxEGzuXwcBAIgDBMAbpAA5WMzcxXDNPzoIgB8YHRkYDGox4Ny/DgIAEAMI gEcQAIiXMEv/WEAA/EB8nIHBMBb/wqz8YQEB8AOjIwODCIABBADAIW99P2EVAAEAeJBHJv81 EAA/EB9nYDCExb0AhHcRAfADoyMDgwEsHmJ+BMAPpAAQJQ9N/msgAAAP8Lb0x0P7kY8AqAXT tuB7Q3ycgUGPFv/er/z3a9BGfgIgTNuC7w2jIwODvgXgfeoPAbiLUK3hVVIAiIppwD/W/aOR mQBIYwaAAEBUmJt/HlGAzASgU43pZVKAHCzm46J1wBeSAljqdWdlvP7k3jb1blMr+oT/EPDX qjIavLO3P8HoyMCgL4v2Uz4CYBeA4yZhqPlVqjZ/9t7+Ajjk6bR/x0MCcOXlmbpp9Qy/U3V/ 9m9r1WnvaXbPtG++vo8AnkAAfhKA/Tt6LRiD/UopqW+XLxOkADlYTN7Fz/f9KSYFuPKy8R3t Uu1rtHm/1tgE8EIA8rCYuouG5p+jAiAAG42q5fiHrNfS/vaOddy3Wt1fWDIAUgCIgC8EIDwP CYBQqu7k+ctiPp+L7by+CUCt5rfJre4nbRkAAgDPY2z+eVwBnpwFqKvTl+cz/xoJvHQBWP/S BKCzZQCkAFlYTNvFr8Z7ISmAaOVLVuJ4wj6+XKk+zm+VNrVvEIBdVGBqAx7fc3OHr8PoyMAg AmDAYSegJWXfXu4Hf6f0UX0uAHZIAeBhYgn5jzwpAJa2nUoP6tVOJM5TADsIADxLPEn/gUev Bfg4G9AnAUoat5iKgGeGJv71IVaYx79AdtbHv8D2HngE/zd1+NAE4PF9mR6nbbcnBBWAWtW7 wt6HaUC7od/27wb/sjeIi99x6b4/4V2MOgVolJC7Xt8PjUBWSAHgIf4eve3HZ2IuArZD/F/p VcBPrcA2EAB4CATgHdFVw9W99TrBP43r48tyGvqdNsQ/XQxkgxQgB4spuvjW93OuAGWkAOrQ 8TOP6+PLSwdwM5UB1ouF5102XQ5stXh/py/C6MjA4H2LV0/5ZQhA1Q0tv2JrBZ7G9OHlZi0F TEpwFADjgiAWSAHgESKM+Q9ktiSYBQQAniDKrH8PAuAH4uMMDN61eL3uV0YKEB4EIAeLybmI AMQCKQAE5VL3z6MgAACuiX3yXwMB8APxcQYGf7b4swCQAvgBAcjBYjIuXuz+uW/wBggAgFvi jvkPIAAAbkEAooMUIAeLibh4p+xHCuAHBCAHi2m4eKvwjwD4gRQAQhH/zN8OBADACZ9v/BUj CIAfiI8zMHjJ4p+L+/6QAvgBAcjBYtwuIgARQwoAnpnG+0/dP4+CAADcJ5Xx/gYC4Afi4wwM XrDoSABIAfyAAORgMWIXXYX8CIAfSAHAJykl/QcQAIC7IACRQwqQg8UYXXS89A8pgB8QgBws Rujin+OlfxAAP5ACgBdcC0B4EACAX3nr+0lPARAAPxAfZ2Dwk0X3A54UwA8IQA4Wo3MRAUgF UgBwT5ox/wEEAOAnUs369yAAfiA+zsDguUUfAkAK4AcEIAeL0bjo78ZfCIAfSAHAHelP/msg AADXQACSgxQgB4uRuOiz+4cUwA8IQA4W43DR6ykfAfADKQC4IvWY/wACAHCB9LP+PQiAHwqN j/MyaLDoue5HCuAHBCAHizG4iAAgAFAiad746zMIAMBn/lzc9ydG8hEAtWDaFnxvioyPczOo WQwkAKQAv7OMf2HaFnxvihoduRrcLE7j3VP3j8lgMPIRgAmhWsOrpABwh4xC/iOZCYA0ZgAI ANwCAdiIWwA61ZheJgXIweJjLoar+pWdApyV8fqTe9vUu02t6BP+Q8Bfq8r4za528WvKGR0Z G5wtBqz7IwB2AThuEoaaX6Vq82fd7SQUR2YTf3viEoCzrXXT6hl+p+r+7N/WqtPe0+yead/s ZP+gNPwt/RMN6QjA/h29FozBfqWU1LfLlwlSgBwsBjf4F3zlj9JTgO/f0S7Vvkab92uNTQAv BCAPiwiAB+IVgEbVcvxD1mtpf3vHOu5bre4vLBkAKQD8wFvfT45JQFwCIJSqOzk/FfP5XGzn 9U0AajW/TW51P2nLABAAuE6eA/5IXAIwUs8zefOZf40EXroArH9pAtDZMgBSgCwsBjb4hACU nQKIVr5kJdbzeKX6OL9V2tS+QQB2UYGpDXh8j9P9/IbcR8cTFsMafCTmL1sAZrZMvh/8ndJH 9bkA2CEFgIvkm/XviVAAKj2oV7u63nkKYAcBgIsgABYCXAuwDfM+CVDSuMVUBDz7xol/fYgV 5vEvkJ318S+wvQceIf9N94X/5313/zhtuz0hqADUqt4V9j5MA9q/0dm+fcu/7A1m6+KTS/+E /xUjFIAtBWiUkLte3w+NQFZIAeBbwnf/PEqEArAWAdsh/q/0KuCnVmAbCAB8y1+QpX+iISIB EF01XPRbrx2A09DvtCH+6WIgG6QAOVgMYnA33vN0cUdEAqAOjUBLB3AzlQHWi4XnXTZdDmz9 ag+7e04Bh06WLu7P+Fm6uCciAai6oRNYLK3AzVoKmJTgKADGBUEskALAd2Qf8h+JSAA8ggDA VxSQ9B9AAPxQQPCYoYvHsl+GLh5BAPxQwKGToYsIwGcQAMiPXO/89xkEAOAv1zv/fQYB8EMB wWNGLtoEICMXbSAAfijg0MnHxWm8G9r/8nHRCgIApVNUyH8EAYDSQQCugAB8RQHBYy4unlT9 cnHxBATADwUcOpm4eFb3z8TFMxAAKJviJv72IABQKgXc+e8zCIAfCggeU3fx7/PSP6m7+AUI gB8KOHRSdxEBGEAAoEze+n7KTAIQACiSUgf8EQTADwUEj2m7+JUApO3iVyAAfijg0Enaxe9i /qRd/A4EAAqk5Kx/DwIABYIALCAAfiggeEzSxWtL/yTp4jUQAD8UcOik6OLftaV/UnTxIggA FMRFASgABADKYRrvdP9oIAB+KCB4TM/Fy+M9PRcvgwD4oYBDJz0XEYB3EAAoBUJ+AwgAFAJJ vwkEwA8FBI+pufiDAKTm4g8gAH4o4NBJx8Wfl/5Jx8WfQQAgd/4+r/xRLggA5A4CcAIC4IcC gsdUXHzr+/leAVJx8QYIgB8KOHQScfHOKT8RF++AAEDeEPOfggBA1pD1n4MA+KGA4DEJF+/V /ZJw8R4IgB8KOHSScBEB+AACABnD1N8nEADIE1b++AoEwA8FBI9xu+ik+yduF52QjwCoBdO2 4HtTwKETt4t/Lpb+idtFJ+QnAMK0LfjewLMQ8n9JPgIwIVRreBUBKAyS/m/JTACkMQMgBcjC 4gWDjgQgZhcdkZkAdKoxvYwA5GDxe4Ou6v4Ru+iKxwSgei/XnZXx+pN729S7Ta3oE/5DwF+r yvRZUoCiYObvex4TAHFVAI6bhKHmV6na/NlbuwqJgQB8z1MC0KrOIABnn6ibVs/wO1X3Z/+2 Vp32nmb3TPvmX3fzZwoIHiN08dqd/1xYdEwxKYDsT9UXBWD/jl4LxmC/zySkvl2+TCAAOVj8 aPDP9Y2/4nPROQ8JQNMP31sC0C7Vvkab92uNTQAvUoBCcC4ABfCMAFTDSP0gAI2q5fiHrNfS /vaOddy3Wt1fWDIABKAIpvF+u/2vLJ4RgFpJowAIpepOzk/FfD4X23l9+8j4DQNyq/tJWwZA CpCFxQ8GPYz32Fz0wCMC0I1natssQD3P5M1n/jUS2H1k/UsTgM6WASAAWVhEADzwhADMY/ZN AEQrX7IS63m8Un2c3yptat8gALuowNQGPL7n3g5DAhDy/8QTAjD369tqflsm3w/+Tumj+lwA 7CAA2UPS/xsPCMBSq7eN3EoP6tWurneeAtghBcjB4qlBLwIQl4teeEAAlvqd9dS9bRj6haVx i6kIaGdpMfzX/wOHefwLZGd9/Ats74GH5d/0b/j/vu7//L7G/zhtuz3hvgAoHfMblr9qVe8K ex+mAe0mf9xViJ8/bvx1hwgFYEsBGiXkrtf3QyOQ3eTvewuRgwDc4sHLgT8WAdsh/q/0KuCn VmCrqV/38Wf+ZW8wEhff+n5cKkAcLnolCgGY/hJdNVz0W68dgNPQ77Qh/uliIKspJzt8hQIO nShc9HvKj8JFv0QkAEtWsDQCLR3AzVQGOKYNpsuBraac7TTEBTH/TSISgKobOoHF0grcrKWA SQne6gamBUFsphztMkQGWf9dMlsSzAIpQA4W3w36rvtF4KJvEAA/FHDoROAiAnAbBACSham/ +yAAkCKs/OEIBMAPBQSPT7oYqPungF8RAfBDAYfO0wLgq/vHbDEMCIAfSAHygpDfGQgAJAdJ vzsQAD8UEDw+52IwASjgV0QA/FDAofOYi+Hq/gX8iggAJAYzfy5BACAxEACXIAB+KCB4DG7R 9Z3/PlPAr4gA+KGAQye0xb/wN/4q4FdEACARHhCAAkAAIA2m8R6g/a8sEAA/FBA8hrX4yHgv 4FdEAPxQwKGDAGRgEAGAJCDk9wQCAAlA0u8LBMAPBQSPIS0+JAAF/IoIgB8KOHQCWnyq7l/A r4gAQNQw9+8XBABi5o87//kFAfBDAcFjEIvPNv8U8CsiAH4o4NAJYXE33vN08VmDCABEDDG/ dxAAiBcEwDsIgB8KCB79Wzwk/Tm6+LRBBMATBRw63i0ey34Zuvi4QQQAooWZvwAgABAf44Bn 7j8ECIAfCgge/Vm0dP/k5GIsBhEATxRw6CAAGRhEACA63jr/SAL8gQBAZDDgQ4IA+KGA4NGX RasA5ONiPAYRAE8UcOh4smiP+bNxMSKDCADEBVl/WBAAiAoEICwIgB8KCB69WDwr/GfiYlQG MxIAtWDaFnxvCjh0HFt87/47KkDyLkZoMEMBEKZtwfcGLvLHnf8eIR8BmBCqNbyKAESPqfsP BfBPZgIgjRkAKUD0Fr8Z7om7GKXB3ASgU43pZQQgcotfnfDTdjFOg9EJQGWu4vXItql321rR J/yHgL9WlemzpACRQ8T/FLEJgLAKwLHELww1v0rV5s862z/wATn/Y0QmAK3qbAJQN62e4Xeq 7s/+ba067T3N7tkGKUDUFr+s+qXsYqwGIxMA2Z/BbQIwsG3rtWAM9vuUQerb5csEAhC1RQTg MYORCUDTj+rvBKBdqn2NNu/XGpsAXqQA0cLaX08TlQBUwwBeBnmjajn+Ieu1tL8JwDruW63u LywZAAIQKabJ/6f3qTCiEoBaSW2Qi/l8Lrbz+iYA41sH5Fb3k7YMgBQgUovXBCBJFyM3GJUA dOMJfB3k85l/jQT0bdq7NgHobBkAAhCnxbfGv3MFSNHF2A3GJADzUN4GeaX6OL9V2tS+QQB2 UYGpDXh8j8v9BEcQ80dARAIwt/FrRcB+8HdKH9XnAmAHAYgRBCAC4hGApYSvD+h++O/qeucp gB1SgAgtXi77pedi/AYjEoClrKcLwNAYLLX3nBcB7SyXCv/r/4HDPP4FsrM+/gW2d/uhZ/2R /ptm/ThZPuMUbwKgdObXalXvCnsfpgHt3+1uN8ERzPxFQdQC0Cghd72+HxqB7N/tckfBBcz9 x0E8ArCgD3Ilp6mA923mVmDrd7rbvS/5l73B3y3+uvRPQi4mYzBmAZDT0O+0If7pYiDrd7rc wa8o4ND51eLP7X/puJiOwZgFYOkAbqYywDE/MF0ObP1O97sJvzKM9++7f8Av8QpAs5b3JyV4 qxCaFgSxfafrnYSfYbxHRXwC4ANSgGgs3jjjp+JiSgYRAE8UcOggABkYRAAgKCT9kYEAQEAo +8UGAuCHAoLHXyzeEoA0XEzLIALgiQIOnUsWp/F+b+YvcheTNIgAQAj+uPNfpDgTgK5WQt7b F38gAA+DAMTKfQEYV/Icr9zX1u6KDFKAZy1O4/1u+1/ULiZq0IEATJfjKdVK66K8j4MAPGrR 0Rk/ZhdTNehAAMalOcYwoPquMf8BSAEehZA/Xu4LwNibf1jQNzZi3a8yIOmPGEcCIOY8wMUu eYAU4EGLzsp+8bqYrkEnKUA135Tvq+X5HgEBeNAiAhCxQSdFQCG7cehTA4B3mPmLGhfTgAPT 2j3MAoAGc//x46ARqBLj6lzaUt3RQQrwhMU/x7f+jNDF5A3SCuyJAg6drwTgbvPPJYPOKeBX RADAE4T8KYAAgB9I+pPAhQDIpo62A2CCFCC8RfcCEJ2LGRh0IQDtslSvUPL+DnkBAQhu0UPd PzYXczDoZhqwk1o/cIzEHZ/kCDN/ieCiEaiZm4BpBIIFBCARHF0NONUAaAVeKSB4PLPopfkn LhfzMOjqYqBZAGI90yIAwSyOw91P+18sLuZk0IkAyHnoczEQ/LH2V1rcFwAxXQ34GqYDqAGU jqn9FwWImPsCMA77QQBkrb67VWd4SAECWfQ63ONwMS+DLvoAaiWqPg9o62gzAAQgkEW/J/wo XMzMoAsBkGK+bXe0iwKTAgSCiD85nFwL0IpaKRFrF9ALAQgEOX96cDGQHwoIHt8s+q76ReBi dgYRAE8UcOggABkYRADAFUz8pQgCAPeh+SdZbgmAesPhnrmEFMCrRVP3j1eDoSjgV0QA/FDA obMXgADdfwiAB0gB4C6E/AmDAMBNSPpTBgHwQwHB42IxmACQAnjAiQB0olY1nYA6BRw6s8Vw dX8EwAMu7gxUL9cCVE526UfOCpGkAN5g5i9t7guA7M/+rXyNVwNKF7v0I8v4N61JgAB4AwFI Gyd3B57/EsPyoA8jjGsSkAJ44H3xL88GSQE84GJR0CXyr55fEECaWxEQAPcE6v7RQAA84GhR 0Lc/H6IzByGP71eGhBcA8ICLCGD7si8jADlNGxyD9fN+Qtke7kDWij7hP3zHFo7sv/m7/YLv eev8QwGSxNGioCNf3xhkGeiN+WXzPh03CUPNz5aEkAK45okBTwrgAUeLgo6YC3AGRFcNYYA6 vP88g6ibVs/wO1X3n27r3e3IGsvNyRAA1yAAeRh00QfQrdOAF1uBusP5+nMJYXtHrwVj4FGN tyXYtsuXCVIAxxDz54KLIuCvlwQeS/ZXBKBd8odGCyOsNyZAANxC1p8NzwrAWQTQLH1Fsl6L Bds71nHfapUEYYtBSAHc8owAkAJ44MmLgdpDFVApoVTdyfmpmM/nYjuvbwIw3pJ0QFMRacsA EAC3PFT4RwA88JwADEXA/Zzd4ZKC+czfaB3GmwCsf2kC0FlnIUgBHOHx1p/wCA8JwDSDd5iz F618yUqs5/FqmCZodZkwCMAuKrDNQiAAbvjj1p+58aQA1I00bdsy+X7w7+cKzwXgxNxve3mD PINHU/dfOAUgBfDAgylAf643Xj5Y6UG92tX1zlMAOwiAE/bDPUsXH7aYogDcWBTUkrRvX9Mn AUoat5iKgHaW3fvX/wPz+PUxn/Af3w8eLh6/ruPrUgBs1+5pw7zeacSHaUAr1ABcQM6fIe5S AGnrw7VjFoAtBWiUkLv+wg+NQFZIARxwzPkzdPFxi+FddFkDEOZL8eyYU4C1CNgO8X+lVwE/ tQLbQADu81b1y8/F5y2mLQDfXg0oukoORcBmmeGbxvV0idC2spichn6nDfFPFwPZIAW4DxN/ WeJSAL6qx730qkG7vKC/vDQCLR3A85pjx0KD6XJgq8Wv9gtOYOo/T9wKwHffNq4HMqwjLped GD9XdUJ/tVnlZFKCt0qjaUEQC6QAd7A0/+TkYiwW004B2ufXBLSAANzA1P3j16IFBMADDmcB 2vqbGblHIAW4wV+YW3/CIzjtA3j0vgBnIAC/w3jPGocCsF3IGx2kAD9jP+Nn42JEFlNOAWIG AfgZBCBrgwgAnELSnzkIAJxA2S93MrszkAVSgB85E4BMXIzKYoopAAJgIo9D53TmLw8X47KI APgh1v2KGNb+KgOXAnC80Uc8IABXsbX/QWbcE4DjHQGuLggQClKAq3zR/pe6izFaTC0F2A// OtbxjwBc5ZszfuIuRmkxNQEYvyGB+DqBXYwKYv5iQADgHQSgGGgE8kPSweN3Zb+kXYzUYoop QAogAFf4svCfsouxWkQA/EAKcAVm/grilgAcZwGjLQfEul9Rwtx/SSAAfkgyeLx2798kXYzc IimAHxCAb/i7du/fFF2M3SIC4IdYI5O4MLX/kgRkDgIAMwz3EnEhALKpo83+J0gBPnP5hJ+e i/FbTDIFaJfyn1Dy/g55AQH4DAIQgcUUBaBSqpvuCdRxNWC6kPOXyX0BaIbbgYwC8O3NQcOD AHyCql+h3BeAWsn19p4sCLKQWvD4gwCk5mIKFlNMAcaxv9zf18Ee+QAB+MAvE3+JuZiExTQF QM5D/9vbg4cnVmGKARb/K5r7AiBUNQtASw0gPUzdP0/vE4TjvgCMw34QAFmr1s1OOYcUwMrf z/f+TcbFhCymmAK8aiWqPg9o62gzAATAyo0zfioupmQxSQGQIva7g5MC2CDmLx0n1wK0olZK xNoF9EIArCAApcPFQH5II3i8VfZLw8W0LKaYAkQ7+a+BABi5V/hPwsXELCIAfkhgF5+AmT9w 0QrsZk98ksAuPgBz/+DkYqDKza54hBTggIv2v8hdTNJiiilAvNcAbiAAe5y0/8XtYpoWUxSA V6dE7DEAKcCe39v/IDNcFAHjWBb8bB8QgB2Md1jITwBMCQkpgI6jM37MLqZqMckUICqE8YIk BEAHAYjWIgJwE2kOQkgBNEj6YSMzAeiGBQrfQQA2KPuBRkwCIDtRq1pYFhWQ7eH2A63oE/7D m2tzUwIpwIYzAYjXxXQtlp0CLGU840n8dawyCkPNr7IsSYAArLib+YvWxYQtli0AoquGMECZ Fxaqm1bP8DtV929r6929CBrLnQlIARaY+4cdMQnATGdfWWgTgF4LxmC/Gtck3bbLlwkE4HX1 5t9QBhEKgKWSP7BtaZdEodHiBeuqpKQAHu79G5+L6VssOwWYmVcXb5YlxmS9VgU2AVjHfauV DITt3mQIwCwAQS26BgHwQIQCsAxpMZ/PxXZe3wRgvB/RgHYzAmnLAEgBaP8FM9EJwFAEnKby 5jN/oy02ugnA+pcmAJ31ukQEgJwfjMQlANPE3jKVXw3zAa3SpvYNArCLCmz3JSAF8CAAsbmY g8XSU4BpdfFGzk/7wb+fFDwXgJPvdbWDXxPZoeOj7B+Zi1lYLF0AemQltpi/H/67ut55CmCn 9BSAiT+wEJ0AvPRcvk8ClNS2nBcB7Sw9hv96hS3xoQvA0/vCI47Hr1fwBxCArRGgVvWusPdh GtBK4SmAn96fqFzMxGJ4F6MWgEYJuev1/dAIZKVcAfB48+9YXMzJIgIwsKQA7RD/V3oV8FMr sI1iawCm9r+n9wliIiIBEF0lhyJgM49tOQ39Thviny4GslG0ALhs/4XciEgAtpUFp1P+0gHc TAHBceFB0+XA1q/2sb+nxBE8eh3vcbiYl8WiU4BxPRBVi06OT5u1vD8pwdvKo6YFQSwUKgB+ z/hRuJiZxaIFwCOFpgCE/PAJBCBfSPrhIwiAHyIIHn2X/SJwMTuLpAB+QACCWPQMAuABBCBX mPmDL0AAMsRj+x9kBgLghyeDx0DtfwXExwW4iAD44WkBCND+V8DoKMBFBCA7CPnhexCA3CDp hwsgAH54LngMJgAFxMcFuIgA+OGxQydc3b+A0VGAiwhAXjDzB5dAAPICAYBLIAB+eCh4DNn8 U0ATvdRnAAAW6klEQVR8XICLCIAfnjl0grb/FTA6CnARAcgEbv4Nv4AA5IGp/RcFgI8gAH4I Hcs9MNoLiI8LcBEB8EPgX/KJ830Bo6MAFxGAHCDihx9BAHIAAYAfQQD8EDSWe6boV0B8XICL CIAfQv6SD5X9CxgdBbiIAKQP837wMwhA8jDzD7+DAPghTCz36OqfBcTHBbiIAPghyC9pav8L YXeigNFRgIsIQML8cfNvuAkCkC6Md7gNAuCHALHc/oxPfJyDRVIAPyAAHihgdBTgIgKQKiT9 4AAEIFEo+4ELEAA/eI/ljgJAfJyDRVIAP+QnAG8zf4yOHCwiAH7ILgVg7h/cgACkBqt/gkMQ AD94i+VM7b/DS8THOVgkBfBDbgIQ0qCVAkZHAS4iAGlBxA9OyUcA1IJpW/C98QQ5P7glPwEQ pm3B98ZTLGcXAOLjHCySAtxFqNbwai4CcFL2Z3TkYBEBuIk0ZgC5pABM/IFrMhOATjWmlxEA ACNPCIDsRK1U3VTHfTkp4/Wfapt6t6kVfcJ/CPhrdfzS6Ztv7O1v+IjlTnt/iI9zsFhGCrAO 9M7y+smntufCUPOrVG3+7L0d/gHHv+Tn1T8ZHTlYLEMA6q6V/WBt1OF0bRn5y6eaVs/wO1X3 Z/+23qlIc9SU5Zt/3dVIMLX/Pb1PkAVP1gC6w5TduQDs3yFn9aiUkvp2+TKRgwAY2n8B7vKk ABxL9lcEoF2qfY0279camwBeyacA34x34uMcLJaRAmzGzwSgUbUc/5D1Wtrf3rGO+1ar+wtL BpC4AHx1xmd05GCxLAGo3lIAoVTdyfmpmDeL7W2bANRqfpvc6n7SlgEkngIQ8oM3nhSAY9fe PAdQz6XB+cy/RgIvXQDWvzQBONYUtG92sr8PQdIP/nhQAJrjeBWtfMlKrOfxSvUK0epzBQYB 2EUFpjbg8T23d/Yq7mK5L8t+xMc5WCwpBei0M/uOLZPvB3+n9FF9LgB2EAAPFDA6CnDxMQHo jl0AK5Ue1O+7hc5TADsJpwDM/IFPnhIA+/jXh3mfBChp3GIqAtpZWgz/9Qqb1uMw9//4/vDI 5XHadnuCGwE4G/+7YV7vCgUfpgHt33h9D2/yz8F3fO7/dWzwGsEt4qIHnhGAfWZ/YEsBGiXk rtf3QyOQlSQF4Fr7H6MjB4uFCMDp+N+KgO0Q/1f6ez+1AttIsgZAzg/+eUIA3sb/NK5FVw0X /dZrB+D0tk4b4p8uBrKRogBQ9YMAPHo58DK0p3G9vLY0Ai0dwHO/wPahabPpcmCrxfs7fZHb sdzVuj/xcQ4Wy0gBLAJQdUMnsFhagZu1FDApwVEAjAuC2Cze3+mLIAAZGCzBxcyWBLOQXgrA 1D8EAQGIEpp/IAwIgB9uxnLXBYD4OAeLpAB+SE0Afuj/ZXTkYBEB8ENiKcDX7X8AN0EA4mIc 7QgAhAIB8MOPsdyfYfnf7xSA+DgHi6QAfkhLAEIavEEBo6MAFxGAmCDih8AgABFBzg+hQQD8 8FMsd0cAiI9zsEgK4Ic0BOBW2Z/RkYNFBMAPSaQATPxBeBCAaEAAIDwIgB+ux3I3e3+Ij3Ow SArgh8gF4NLqny4MOqGA0VGAiwjA85ja/57eJygEBOB5/i4t/wvgEATADxdiOTfjnfg4B4uk AH6IWQAcnfEZHTlYRAD8EHMKQMgPD4IAPAxJPzwJAuCHb2M5Z2U/4uMcLJIC+AEB8EABo6MA FxGAR2HmD54FAXgS5v7hYRAAP3yO5Vz0/14y6JoC4uMCXEQA/PDxl3Td/sfoyMEiAuCHCFMA In6IAQTgGcj5IQoQAD98iOXcV/2Ij3OwSArgBwTAAwWMjgJcRACegIk/iAQE4AGY+odYQAD8 cBrL+RAA4uMcLJIC+CEuAfDS/cfoyMEiAuCHqFIA+n8hHhCAkIyjHQGAeEAA/GCM5f4My/+6 UgDi4xwskgL4ISYBCGnQKwWMjgJcRADCQcQP0YEABIOcH+IjHwFQC6ZtwffGEMv5FQDi4xws kgL8zjL+hWlb8L15/yU9l/0ZHTlYRADuIlRreDWCFICJP4iRzARAGjMABADATGYC0KnG9PLz KYD33h/i4xwsFp0CyE7UStVNZdncNvXu/N6KPuE/BPy1Mn76cQHw3/3H6MjBYtECsJbxu5PN 23NhqPlVqjZ/1t1eXsfx8r8ADolIAOqulf0YbpT5LF43rZ7hd6ruz/5tvZOLxiYeDnfzKn+O l/8FcEhEArDQGWfyRjYBkLNMVEpJfbt8mXgyBQg03ImPc7BYdAqwYKnkD2xb2qXa12jzfq1N Oh4UgFAnfEZHDhYRgIFpmDeqluNTWa+l/U0A1nHfanV/YckAHkwBCPkhaiIUgGo+j4vD/1+6 ANRKTn/Ire4nbRkAAgBgJkIBWJr55jP/Ggm8dAFY/9IEwF48eCwFCFf1Iz7OwSIpwDDgl2Fc qV4KWn1SwCAAu6jA1AY8vsfxPn5m+iUD1v0ZHTlYRACG6T25/N0P/k7po/pcAOw8lQIw8QeR E5sAdLsugO7QFnSeAth5SACY+ofYiUwA9uN/SAKU1J6fFwHtLD2G//oQK8zjX/84NP/4tfkv nG9PPf5FsA/5PE6WzzjFqwAcxn8/zOtdYe/DNKCVZ2oAQbv//vn9+hgs4qIHohKAfcI/1gPl rtf3QyOQlfAC4G/5XwCHxCQAx/HfDvF/pb/4qRXYRnABYLhDGkQkAMfxL6fnnTbEP10MZKMA ASA+zsFi0SmA2pDD86UDeG4M2LZObzddDmz9ag+7e8YDET+jIweLCMAmAM1a3p+U4CgAxgVB bF/tfGdPIeeHVIhIADyCAAAYQQDc80jZn/g4B4tFpwAeCSoAz0z8MTpysIgA+KEAAQD4BQTA NfT+QEIgAI55qvuP+DgHi6QAfggjAONoRwDyMViCiwiAM8bhzgUAkBQIgDMY7ZAeCIAr9uf7 AoJHXMzAIALgikPEX8Chg4sZGEQAXEHKDymCALiBoh8kCQLghLeyfwHBIy5mYBABcAMCkKPB ElxEAFzAzD8kCgLgAHp/IFUQgJsMw90gAAUEj7iYgUEE4CbDeDe1/xZw6OBiBgYRgJsQ8UPS IAC3IOeHtEEA7mCv+hUQPOJiBgYRgFsgAFkbLMFFBOAGTPxB6iAAv8PUPyQPAvA7ZwJQQPCI ixkYRAB+57T7r4BDBxczMIgA/Az9v5ABCMCvIACQAQjAL3xe/reA4BEXMzCIAPzCFyf8Ag4d XMzAIALwC0T8kAsIwHXI+SEbEIDLfFX1KyB4xMUMDCIA10EAHrKIix5AAK7CxB9kBAJwEab+ IScQgIt8KQAFBI+4mIFBBOAi33b/FXDo4GIGBhGAa9D/C3mBAFwCAYC8yEcA1IJpm4PvN9wA 4EQBCggecTEDgxkKgDBtu//1F8/3BRw6uJiBwYwEYEKo1vBqeAEASILMBEAaMwAHAkDKD1mS mQB0qjG9fFsALhf9CggecTEDg88IgGyb2nCqPivjGT7Uij7hPwT8tapMn0UAcrCIix54RAAs w/xcAI6bhKHmV6na/NkbOzvAvB9kyiMCUDetKVm3jHzzhzpV92f/tlad9p5m90z75t/2c4GZ f8iVx2oAlwVg/45eC8Zgv1JK6tvly0R4ASggeMTFDAwmKwDtUu1rtHm/1tgE8LorAL80/xVw 6OBiBgYjFoBG1XL8Q9ZraX97xzruW63uLywZwD0BoP0X8iUuARBK1Z2cn4r5fC628/r2oVrN b5Nb3U/aMoDfBcDQ//vrVwFESFwCMFLPM3nzmX+NBHYfWv/SBKCzZQA/C8Aw3r/v/9cpIHjE xQwMRiUAopUvWYn1PF6pPs5vlTa1bxCAXVRgagMe3/PjTv5+wi/g0MHFDAxGJQAzWybfD/5O 6aP6XABOjP2wgy/6fyF/IhSASg/q1a6ud54CnBi7vn+vH9r/AFIjQgHQNvVJgJLGLaYi4Jmx iX99iPX9YxaAS59ZHv9++Mytx7/A9h54BP83zfpx2nZ7QlABqFW9K+x9mAa0f+P1/bvZ//vv lw/dIbhBXMzBYIwRwJYCNErIXa/vh0Ygu7EfdpCZPyiACAVgLQK2Q/xf6VXAT63AVmM/7CAC AAUQhQBMf4uuGi76rdcOwGnod9oQ/3QxkNXY9f272fxTQPCIixkYfPJy4K0CMf1/eW1pBFo6 gJupDHD8kOlyYKvBy7t4t/2vgEMHFzMwGJMAVN3QCSyWVuBmLQVMSnD8kHFBEJvBy7tI/y8U QWZLglm45OW19b8BUgYBOOJmtBcQPOJiBgYRgDcQgFgt4qIHEIADBPxQEgjAHlJ+KAoEYI8r ASggeMTFDAwiAHucVf0LOHRwMQODCMAO5v2gMBAAHQQACgMB0HDY+lNA8IiLGRhEADRcNv8V cOjgYgYGEQANun+hOBCAFfr/oTwQgAnXo72A4BEXMzCIAEw4P98XcOjgYgYGEYAJAn4oEwRg gJQfCgUBeHm5AqiA4BEXMzCIAAwgAElYxEUPIAAOrwACSA0EgAsAoGAQAD8CUEDwiIsZGEQA XF4BpFHAoYOLGRhEAGj/hZJBABAAKJiiBeDP3xVABQSPBVDAr1iyAPg84Rdw6OjY7/WcNAX8 iggAOCBTASiAggWAnN8dCECqlCsAfqt+BQSPOiEE4AGxLuBXRAD8UMChoxNAAJ4I1wr4FYsV ACb+PlF1QqlatNOzfohXolZ1Iy1be4San75aJfrXVqbXxo9Xv+4OP5UXShUApv4/sozeZn7W TU9radw6/HcY9hODFOwFQNbz3+3RznfwU/kBAfBzVGUQPIpW9uO2H/bjSbsfuqKSsq1VZ9w6 vlhPz16VqtevqdT4CTF8/CUbpeQvO/OMWGfwK36iUAHw3v2Xz6HTTif55VzfamNb3zo+6+Y3 NbNKvMbx37y04GB5y0UQAE+UKQD0/36PnEb8cuaW+3rfulXfKLfTfB/5jwNezLHB8oGL8FP5 AgHgqLLRiXqr4a3jfvnDuHUqA25n+X78T2f+el8RuAi/lTeKE4DhCPJ1AYBG+sGjrHcj9iAA lq1TgrCUAsbMf/lUigKQ/q/4kdIEINQhlP6h06ixzrcM7oMA2LYOY38rE4hlzuC1JQU/8Fi4 lv6v+BEEAMwckv6DANi2DtH/2g7QrONfaxG4DgmbRwoTAI6gr1mGeHMqAMetvSCsc4DLHOH0 9y+1vwkEwCNlCUC4Qyj94HGYuH/JSphrALatgyLMc4D6+B9yg7qVYwPh1R0JULGxkf6v+JF8 BOCsxoQAXKea/zk7owDYto4b5PxGYydgStcNpv8rfiQ/ATCdYWYviSKvUDX9Wbs/z5unAS1b h1P9e+F/fD7OG4pOBtp9+Ip8BGDCXGyavCSPDEGtfr7eB8KTmQBIc4QZXgAKCB7NVDeqfdFR wK+YmQBYOs1HL4MWkgo4dIzIO/N90VHArxiTAMi2zyutO/S2tRV9Snk42izx5/AxJpP8Y6vB QLTEJADnReLjVmGo+dniTwQgDGpbMATSICYBqJvWksMbtnaq7s/+6+XpE83u2YYKPptcQPBY AAX8ijEJwMD5NPG2Vc5dJtWuydzWcR5+7rmAQ6cACvgVUxWAdqn2NVrRqbUloOEFILhFXMzB YgIuBhOA9UqSZU2Jw9Z53Lda3V9YMoAU/l2TM4iLORiMWADWa8nFdl7fttZKTn9oK8xIWwaQ wr9rcgZxMQeDMQvAfObXrinVtmqXn60C0FmnoBL4d03OIC7mYDBmARgKfG0f4mtT+wYB2EUF th6UBP5dkzOIizkYjFoAhsHf7RaSPxeAk291sm9X4NDJwCAuGgg6C9CtF5cft5pSgJNvdbFr l+DQycAgLhoIKgDbxeXHraYi4Nm3AoCJqyM0qADUqt4V9j5MAwKAZ0IKQKOE3PX6fmgEAgDP BBSAdoj/K70K+KkVGAD8ErAPQM23mVHSsNV4MRAA+MX75cBrYWLpAG6mMsCxbGG6HBgA/BJM AJq1vD8pwVvd0rQgCAB4Je4lwQDAKwgAQMEgAAAFgwAAFAwCAFAwCABAwSAAAAWDAAAUDAIA UDAIAEDBpCgAoZqG329u6Ney7EQ93I1Lux+ib1dHk7VuIcA/brVbt8K3wfelMvy7OP6rbr+j Z4OG5UC+t5igAAS7bOhtiRXPltefcb0i0ruri8V1FZYQ/7hC/1cN5uJq0rtFWe8t+ja4jf/F xAWL6QlAuAuHjzc39G257lrZnx+bdeFk/66KrhrCgHWRhhD/uO2wNOzyxL/B4ypZ3i32419U so8fRSCDC+KXXzE5AQi8dMh+QYMwlpcbIoRztZsv1QxhcVj1UVsD1rvBgwD4tyj2q9oF+xXX k9Uli8kJQODFw/TUMZTl5ZcM52pIi01/dG7XgPs3eBAA7xaPy9oG+xW7xdAli8kJQODlQ7XD J5zl2Wg4g8tBG8BiNYQ3679qAIMHAfBusTsE3sF+xXrJHC9ZTE4Ari0gfhvt8AlmuZpTgHCu LkdKAIujifVfNYBBpYRSdSdDWRSqqsZJABnI4Mx2L+1LFpMTgGu3EHFnLqDlpZgTyuBQBKwC WZzOj6udAC7OBfK6CmSxHmqcI6H+TSfWEuA1i+kKwFc3EXNoLpjlZpHyIAan+aLj6PBlcT4k 3wXAn4uilS9ZiaUg5t3iOKvam2xmi4EOG2my84VFBOBbc6Esd+vtk8MJwBKverc4n6ZCCsBq uQtjcZ1/n2cDArnYbPl+IQKQaQrQbbdPDpYC9OfHSXR8W1zy1JApwEw1GwiQAsw/YHWIdvy6 qE355Z0CZF4E1MZ/SFfn1gPfFpfvD1kEXFhXp/dssV6G4hyUh3Gx1dr+8i4C5j0NqI//kK7K Ze12vxaVTgiDO9uvIBabgwCEcXErAeY+DZh1I9DWkxvI4MJ8sPq2+CYA4VxcUgDvFttDChDE xd25Pu9GoGCdlRNBW4H34z+kq3MKEMpiyFbgmaUI6N2i3IqAXRCDA43efXTJYnICEPgugiEv BjqM/wCuiq6SQxFwvf4o0D9uwIuBpsudegPL3Ip3i91+GjDIv+l+qGd9MVDwy4HDXdephccy iEHN4qI8Yf5xA14OvDhYr7UV7y42u0agEP+m7eHLs74c+BVsQZA3AfBs+V0AfLs6L0Ei1kbZ QP+4ARcEqTpx8NC/i63eChzCoDgm+1kvCAIArkAAAAoGAQAoGAQAoGAQAICCQQAACgYBACgY BACgYBAAgIJBAAAKBgEAKBgEAKBgEACAgkEAAAoGAQAoGAQAoGAQAICCQQAACgYBACgYBACg YBAAgIJBAAAKBgEAKBgEAKBgEACAgkEA4DL6jX0gbRAAuAwCkA8IAFwGAcgHBAAugwDkAwIA XyGb4T7CTbXdxHh8eboR7nwj7P61441xIXIQAPiGahv2mgDIev57uhO1Ut30tK6e3Vv4GgQA vkEo0Q9q2YrhyZoCDK/KPjhQSk6vj++qhKof2k24CgIA3zAP8eXJ9P9WiemPTjXT6/PAr1UX btfgDggAfMNuSC8CINQc6stp5C+pwKYMEDsIAHxDO4T33VbsG1kqAEtJcA0TJDlAKiAA8BXt NNrHOGARAPUmAMu7mShMBQQAvkS2nZgUYBMAuXsHEUB6IABwgXYc2VsNoN1tpQaQHggAXECO Y38RgO5womcWID0QAPiGuqvkOMM/nNrX8V2ruh1e7qYTPn0A6YEAwDcstb6xx6976wRU85vo BEwNBAC+QXZiuBagk+Ozrl7G/PiymF/mWoD0QADAGUz+pQcCAM5AANIDAQBnIADpgQCAMxCA 9EAAwBkIQHogAAAFgwAAFAwCAFAwCABAwSAAAAWDAAAUDAIAUDAIAEDB/A+kwgw7z5DTYAAA AABJRU5ErkJggg== --------------0E94144F7479196F45AB2851 Content-Type: text/x-patch; name="reltuples-avg.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="reltuples-avg.patch" *** /tmp/DqhRGF_vacuum.c 2018-03-02 18:43:54.448046402 +0300 --- src/backend/commands/vacuum.c 2018-03-02 18:22:04.223070206 +0300 *************** *** 780,791 **** BlockNumber scanned_pages, double scanned_tuples) { - BlockNumber old_rel_pages = relation->rd_rel->relpages; double old_rel_tuples = relation->rd_rel->reltuples; ! double old_density; ! double new_density; double multiplier; - double updated_density; /* If we did scan the whole table, just use the count as-is */ if (scanned_pages >= total_pages) --- 780,788 ---- BlockNumber scanned_pages, double scanned_tuples) { double old_rel_tuples = relation->rd_rel->reltuples; ! double new_rel_tuples; double multiplier; /* If we did scan the whole table, just use the count as-is */ if (scanned_pages >= total_pages) *************** *** 801,839 **** return old_rel_tuples; /* ! * If old value of relpages is zero, old density is indeterminate; we ! * can't do much except scale up scanned_tuples to match total_pages. */ ! if (old_rel_pages == 0) ! return floor((scanned_tuples / scanned_pages) * total_pages + 0.5); /* ! * Okay, we've covered the corner cases. The normal calculation is to ! * convert the old measurement to a density (tuples per page), then update ! * the density using an exponential-moving-average approach, and finally ! * compute reltuples as updated_density * total_pages. ! * ! * For ANALYZE, the moving average multiplier is just the fraction of the ! * table's pages we scanned. This is equivalent to assuming that the ! * tuple density in the unscanned pages didn't change. Of course, it ! * probably did, if the new density measurement is different. But over ! * repeated cycles, the value of reltuples will converge towards the ! * correct value, if repeated measurements show the same new density. ! * ! * For VACUUM, the situation is a bit different: we have looked at a ! * nonrandom sample of pages, but we know for certain that the pages we ! * didn't look at are precisely the ones that haven't changed lately. ! * Thus, there is a reasonable argument for doing exactly the same thing ! * as for the ANALYZE case, that is use the old density measurement as the ! * value for the unscanned pages. ! * ! * This logic could probably use further refinement. */ - old_density = old_rel_tuples / old_rel_pages; - new_density = scanned_tuples / scanned_pages; multiplier = (double) scanned_pages / (double) total_pages; ! updated_density = old_density + (new_density - old_density) * multiplier; ! return floor(updated_density * total_pages + 0.5); } --- 798,825 ---- return old_rel_tuples; /* ! * Estimate the total number of tuples based on the density of scanned ! * tuples. */ ! new_rel_tuples = floor((scanned_tuples / scanned_pages) * total_pages + 0.5); /* ! * ANALYZE scans a representative subset of pages, so we trust its density ! * estimate. ! */ ! if (is_analyze) ! return new_rel_tuples; ! ! /* ! * VACUUM scanned a nonrandom sample of pages, so we can't just scale up its ! * result. For the portion of table it didn't scan, use the old number of tuples, ! * and for the portion it did scan, use the number it reported. This is ! * effectively an exponential moving average with adaptive factor. */ multiplier = (double) scanned_pages / (double) total_pages; ! return floor(old_rel_tuples * (1. - multiplier) ! + new_rel_tuples * multiplier ! + 0.5); } --------------0E94144F7479196F45AB2851--