50 lines
3.6 KiB
XML
50 lines
3.6 KiB
XML
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 760 650" role="img" aria-labelledby="title desc">
|
|
<title id="title">Как читать EXPLAIN ANALYZE от результата к первому расхождению</title>
|
|
<desc id="desc">Вертикальное дерево плана показывает Result, Filter и Index Scan. На каждом уровне сравниваются оценка строк, фактические строки, loops и buffers; расследование начинается с первого расхождения снизу.</desc>
|
|
<defs>
|
|
<style>
|
|
.bg { fill: #f8fafc; }
|
|
.node { fill: #ffffff; stroke: #94a3b8; stroke-width: 2; }
|
|
.scan { fill: #ecfdf5; stroke: #059669; stroke-width: 2; }
|
|
.warn { fill: #fff7ed; stroke: #ea580c; stroke-width: 2; }
|
|
.note { fill: #eff6ff; stroke: #2563eb; stroke-width: 2; }
|
|
.title { font: 700 24px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #0f172a; }
|
|
.label { font: 700 18px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #0f172a; }
|
|
.text { font: 15px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; fill: #334155; }
|
|
.mono { font: 600 14px ui-monospace, SFMono-Regular, Menlo, monospace; fill: #0f172a; }
|
|
.arrow { stroke: #64748b; stroke-width: 3; fill: none; marker-end: url(#tip); }
|
|
.dash { stroke: #ea580c; stroke-width: 3; stroke-dasharray: 7 6; fill: none; marker-end: url(#tipOrange); }
|
|
</style>
|
|
<marker id="tip" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
|
|
<path d="M0,0 L0,6 L9,3 z" fill="#64748b" />
|
|
</marker>
|
|
<marker id="tipOrange" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
|
|
<path d="M0,0 L0,6 L9,3 z" fill="#ea580c" />
|
|
</marker>
|
|
</defs>
|
|
<rect class="bg" width="760" height="650" rx="28" />
|
|
<text class="title" x="42" y="52">План — поток данных, не список красивых узлов</text>
|
|
<rect class="node" x="150" y="86" width="360" height="100" rx="14" />
|
|
<text class="label" x="178" y="122">Aggregate / Result</text>
|
|
<text class="mono" x="178" y="152">rows=1 · actual rows=1 · loops=1</text>
|
|
<path class="arrow" d="M330 188 L330 244" />
|
|
<rect class="warn" x="150" y="254" width="360" height="116" rx="14" />
|
|
<text class="label" x="178" y="291">Filter</text>
|
|
<text class="mono" x="178" y="321">rows=100 · actual rows=100 000</text>
|
|
<text class="text" x="178" y="347">первое заметное расхождение: ищем причину</text>
|
|
<path class="arrow" d="M330 372 L330 428" />
|
|
<rect class="scan" x="150" y="438" width="360" height="116" rx="14" />
|
|
<text class="label" x="178" y="475">Index Scan</text>
|
|
<text class="mono" x="178" y="505">Index Cond: state = 'ready'</text>
|
|
<text class="mono" x="178" y="530">Buffers: shared hit/read · loops=1</text>
|
|
<rect class="note" x="548" y="235" width="174" height="164" rx="14" />
|
|
<text class="label" x="568" y="271">Проверить</text>
|
|
<text class="text" x="568" y="302">1. rows vs actual</text>
|
|
<text class="text" x="568" y="330">2. loops</text>
|
|
<text class="text" x="568" y="358">3. Index Cond</text>
|
|
<text class="text" x="568" y="386">4. Buffers</text>
|
|
<path class="dash" d="M545 318 L515 318" />
|
|
<rect class="node" x="76" y="580" width="608" height="42" rx="12" />
|
|
<text class="text" x="106" y="607">Не лечим верхний узел: начинаем с первого места, где оценка потеряла связь с фактом.</text>
|
|
</svg>
|