plananalyze


Nameplananalyze JSON
Version 0.1.0 PyPI version JSON
download
home_pagehttps://github.com/GujaLomsadze/PlanAnalyzer
SummaryPostgreSQL EXPLAIN Plan Analyzer - Extract insights from execution plans
upload_time2025-09-14 15:39:41
maintainerNone
docs_urlNone
authorGuja Lomsadze
requires_python>=3.8
licenseApache-2.0
keywords postgresql explain query performance database analysis optimizer sql plan bottleneck
VCS
bugtrack_url
requirements PyYAML lxml
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # `plananalyze`

# PostgreSQL `EXPLAIN` Plan Analyzer - Extract insights from execution plans Query

## For best results, run `EXPLAIN` like so `EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS)`

``

# Quickstart

1. Run "ANALYZE" on your Query
2. Copy-paste output from PostgreSQL
3. Review details :)

```python
from plananalyze import analyze_plan

plan = """
Hash Join  (cost=12.70..30.50 rows=120 width=743)
  Hash Cond: ((d.name)::text = (employees.department)::text)
  ->  Seq Scan on departments d  (cost=0.00..14.80 rows=480 width=142)
  ->  Hash  (cost=11.20..11.20 rows=120 width=601)
        ->  Seq Scan on employees  (cost=0.00..11.20 rows=120 width=601)
"""

result = analyze_plan(plan, format_type="summary")
print(result)
```

Output:

```shell
📊 EXECUTION OVERVIEW:
   Total Cost: 30.50
   Node Count: 5

🔍 OPERATIONS:
   Sequential Scans: 2
   Index Scans: 0
   Joins: 1
   Sorts: 0
```

# Detailed Response

```python
# Use format_type="detailed"
result = analyze_plan(plan, format_type="detailed")
```

Output:

```shell
📈 EXECUTION METRICS:
   Total Cost: 30.50
   Root Operation: Hash Join

🏗️  PLAN STRUCTURE:
   Total Nodes: 5
   Plan Depth: 0

🔍 OPERATION BREAKDOWN:
   Sequential Scans: 2
   Index Scans: 0
   Index Only Scans: 0
   Bitmap Scans: 0
   Join Operations: 1
   Sort Operations: 0
   Hash Operations: 2
   Aggregate Operations: 0

💰 MOST EXPENSIVE OPERATIONS:
   1. Hash Join - Cost: 30.50 (100.0%)
   2. ->  Seq Scan on departments - Cost: 14.80 (48.5%)
   3. ->  Hash - Cost: 11.20 (36.7%)
```

# JSON output

```python
# Use format_type="json"
result = analyze_plan(plan, format_type="json")
```

# JSON Input

### Run "explain" on PostgreSQL query using `EXPLAIN (FORMAT JSON)`

```python
from plananalyze import analyze_plan

plan_json = """
[
  {
    "Plan": {
      "Node Type": "Hash Join",
      "Parallel Aware": false,
      "Async Capable": false,
      "Join Type": "Inner",
      "Startup Cost": 12.70,
      "Total Cost": 30.50,
      "Plan Rows": 120,
      "Plan Width": 743,
      "Inner Unique": false,
      "Hash Cond": "((d.name)::text = (employees.department)::text)",
      "Plans": [
        {
          "Node Type": "Seq Scan",
          "Parent Relationship": "Outer",
          "Parallel Aware": false,
          "Async Capable": false,
          "Relation Name": "departments",
          "Alias": "d",
          "Startup Cost": 0.00,
          "Total Cost": 14.80,
          "Plan Rows": 480,
          "Plan Width": 142
        },
        {
          "Node Type": "Hash",
          "Parent Relationship": "Inner",
          "Parallel Aware": false,
          "Async Capable": false,
          "Startup Cost": 11.20,
          "Total Cost": 11.20,
          "Plan Rows": 120,
          "Plan Width": 601,
          "Plans": [
            {
              "Node Type": "Seq Scan",
              "Parent Relationship": "Outer",
              "Parallel Aware": false,
              "Async Capable": false,
              "Relation Name": "employees",
              "Alias": "employees",
              "Startup Cost": 0.00,
              "Total Cost": 11.20,
              "Plan Rows": 120,
              "Plan Width": 601
            }
          ]
        }
      ]
    }
  }
]
"""

result = analyze_plan(plan_json, format_type="summary")
print(result)
```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/GujaLomsadze/PlanAnalyzer",
    "name": "plananalyze",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "postgresql, explain, query, performance, database, analysis, optimizer, sql, plan, bottleneck",
    "author": "Guja Lomsadze",
    "author_email": "Guja Lomsadze <lomsadze.guja@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/5e/46/20ca447a39194473a73e07109c8d8acfdc9695bf0f84f130670628766f57/plananalyze-0.1.0.tar.gz",
    "platform": null,
    "description": "# `plananalyze`\n\n# PostgreSQL `EXPLAIN` Plan Analyzer - Extract insights from execution plans Query\n\n## For best results, run `EXPLAIN` like so `EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS)`\n\n``\n\n# Quickstart\n\n1. Run \"ANALYZE\" on your Query\n2. Copy-paste output from PostgreSQL\n3. Review details :)\n\n```python\nfrom plananalyze import analyze_plan\n\nplan = \"\"\"\nHash Join  (cost=12.70..30.50 rows=120 width=743)\n  Hash Cond: ((d.name)::text = (employees.department)::text)\n  ->  Seq Scan on departments d  (cost=0.00..14.80 rows=480 width=142)\n  ->  Hash  (cost=11.20..11.20 rows=120 width=601)\n        ->  Seq Scan on employees  (cost=0.00..11.20 rows=120 width=601)\n\"\"\"\n\nresult = analyze_plan(plan, format_type=\"summary\")\nprint(result)\n```\n\nOutput:\n\n```shell\n\ud83d\udcca EXECUTION OVERVIEW:\n   Total Cost: 30.50\n   Node Count: 5\n\n\ud83d\udd0d OPERATIONS:\n   Sequential Scans: 2\n   Index Scans: 0\n   Joins: 1\n   Sorts: 0\n```\n\n# Detailed Response\n\n```python\n# Use format_type=\"detailed\"\nresult = analyze_plan(plan, format_type=\"detailed\")\n```\n\nOutput:\n\n```shell\n\ud83d\udcc8 EXECUTION METRICS:\n   Total Cost: 30.50\n   Root Operation: Hash Join\n\n\ud83c\udfd7\ufe0f  PLAN STRUCTURE:\n   Total Nodes: 5\n   Plan Depth: 0\n\n\ud83d\udd0d OPERATION BREAKDOWN:\n   Sequential Scans: 2\n   Index Scans: 0\n   Index Only Scans: 0\n   Bitmap Scans: 0\n   Join Operations: 1\n   Sort Operations: 0\n   Hash Operations: 2\n   Aggregate Operations: 0\n\n\ud83d\udcb0 MOST EXPENSIVE OPERATIONS:\n   1. Hash Join - Cost: 30.50 (100.0%)\n   2. ->  Seq Scan on departments - Cost: 14.80 (48.5%)\n   3. ->  Hash - Cost: 11.20 (36.7%)\n```\n\n# JSON output\n\n```python\n# Use format_type=\"json\"\nresult = analyze_plan(plan, format_type=\"json\")\n```\n\n# JSON Input\n\n### Run \"explain\" on PostgreSQL query using `EXPLAIN (FORMAT JSON)`\n\n```python\nfrom plananalyze import analyze_plan\n\nplan_json = \"\"\"\n[\n  {\n    \"Plan\": {\n      \"Node Type\": \"Hash Join\",\n      \"Parallel Aware\": false,\n      \"Async Capable\": false,\n      \"Join Type\": \"Inner\",\n      \"Startup Cost\": 12.70,\n      \"Total Cost\": 30.50,\n      \"Plan Rows\": 120,\n      \"Plan Width\": 743,\n      \"Inner Unique\": false,\n      \"Hash Cond\": \"((d.name)::text = (employees.department)::text)\",\n      \"Plans\": [\n        {\n          \"Node Type\": \"Seq Scan\",\n          \"Parent Relationship\": \"Outer\",\n          \"Parallel Aware\": false,\n          \"Async Capable\": false,\n          \"Relation Name\": \"departments\",\n          \"Alias\": \"d\",\n          \"Startup Cost\": 0.00,\n          \"Total Cost\": 14.80,\n          \"Plan Rows\": 480,\n          \"Plan Width\": 142\n        },\n        {\n          \"Node Type\": \"Hash\",\n          \"Parent Relationship\": \"Inner\",\n          \"Parallel Aware\": false,\n          \"Async Capable\": false,\n          \"Startup Cost\": 11.20,\n          \"Total Cost\": 11.20,\n          \"Plan Rows\": 120,\n          \"Plan Width\": 601,\n          \"Plans\": [\n            {\n              \"Node Type\": \"Seq Scan\",\n              \"Parent Relationship\": \"Outer\",\n              \"Parallel Aware\": false,\n              \"Async Capable\": false,\n              \"Relation Name\": \"employees\",\n              \"Alias\": \"employees\",\n              \"Startup Cost\": 0.00,\n              \"Total Cost\": 11.20,\n              \"Plan Rows\": 120,\n              \"Plan Width\": 601\n            }\n          ]\n        }\n      ]\n    }\n  }\n]\n\"\"\"\n\nresult = analyze_plan(plan_json, format_type=\"summary\")\nprint(result)\n```\n",
    "bugtrack_url": null,
    "license": "Apache-2.0",
    "summary": "PostgreSQL EXPLAIN Plan Analyzer - Extract insights from execution plans",
    "version": "0.1.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/GujaLomsadze/PlanAnalyzer/issues",
        "Homepage": "https://github.com/GujaLomsadze/PlanAnalyzer",
        "Repository": "https://github.com/GujaLomsadze/PlanAnalyzer.git"
    },
    "split_keywords": [
        "postgresql",
        " explain",
        " query",
        " performance",
        " database",
        " analysis",
        " optimizer",
        " sql",
        " plan",
        " bottleneck"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "7fc3bf1c6bde8e2d20a594e6512b3b823b6d58cfdb79ce42b4a8240fdd69a3fb",
                "md5": "b6ad6b5cd293276915f5eab5e728386d",
                "sha256": "94ebb9be8599c163f50e8e21f91bfe1503d9e35ce46d1705110a3ab9d6f470be"
            },
            "downloads": -1,
            "filename": "plananalyze-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "b6ad6b5cd293276915f5eab5e728386d",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 30172,
            "upload_time": "2025-09-14T15:39:39",
            "upload_time_iso_8601": "2025-09-14T15:39:39.048931Z",
            "url": "https://files.pythonhosted.org/packages/7f/c3/bf1c6bde8e2d20a594e6512b3b823b6d58cfdb79ce42b4a8240fdd69a3fb/plananalyze-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "5e4620ca447a39194473a73e07109c8d8acfdc9695bf0f84f130670628766f57",
                "md5": "8aae27875652f9121f0c1c1b26b31310",
                "sha256": "30ff96a8e32ee235fb67b472e52d0da330eba7563a3928bc3ae9bc35aecfcb1a"
            },
            "downloads": -1,
            "filename": "plananalyze-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "8aae27875652f9121f0c1c1b26b31310",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 29475,
            "upload_time": "2025-09-14T15:39:41",
            "upload_time_iso_8601": "2025-09-14T15:39:41.140752Z",
            "url": "https://files.pythonhosted.org/packages/5e/46/20ca447a39194473a73e07109c8d8acfdc9695bf0f84f130670628766f57/plananalyze-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-14 15:39:41",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "GujaLomsadze",
    "github_project": "PlanAnalyzer",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "PyYAML",
            "specs": [
                [
                    ">=",
                    "6.0"
                ]
            ]
        },
        {
            "name": "lxml",
            "specs": [
                [
                    ">=",
                    "4.9.0"
                ]
            ]
        }
    ],
    "tox": true,
    "lcname": "plananalyze"
}
        
Elapsed time: 4.65693s