Article · 2022-03-24

SQL Views for API Query Performance: A Real-World Optimization

Serving high-volume location queries exposed several performance bottlenecks:

Optimization Strategy

We addressed these constraints with four complementary techniques:

  1. SQL Optimization: Replace iterative queries with batch queries to reduce database interactions
  2. Pre-built Views: Consolidate multi-table joins into a single view, lowering query complexity
  3. In-application Ordering: Restore results to the caller's expected order when needed
  4. Data Field Reduction: Return only essential fields to compress transfer size

Detailed Optimization Process

1. From Iterative to Batch Queries

The original logic queried information for each location ID separately (Python example):

for entity_id in entity_id_list:
    query_entity(entity_id)
    query_supplier(entity_id)
    query_delivery_info(entity_id)

This works for small datasets, but with thousands of IDs per request, a single API call triggered thousands of SQL round-trips, severely degrading response time.

Improved approach:

Use SQL IN clause to fetch all required data in one query:

entity_infos = query_stores_batch(entity_id_list)

A single SQL statement now retrieves all information, dramatically reducing database load and network overhead.

2. Consolidating Logic with Views

To further simplify SQL and reduce backend assembly, we built an aggregated view that pre-joins fields scattered across multiple tables:

CREATE VIEW entity_view AS
SELECT 
  s.entity_id, s.name, s.location, 
  n.partner_id, n.partner_name, 
  f.ship_time, f.ship_limit_price
FROM 
  entity_table s
INNER JOIN 
  partner_table n ON s.entity_id = n.entity_id
LEFT JOIN 
  shipping_table f ON n.partner_id = f.partner_id
WHERE 
  n.state = 'active';

Views provide immediate benefits:

3. Restoring Caller-Supplied Order

Batch queries improved throughput, but results rarely preserve input order. Some business logic depends on ordering—by distance, priority, or other criteria.

We added an ordering recovery step in the interface layer (Python example):

# 假设 result_map 是 {entity_id: entity_info} 的字典
ordered_list = []
for entity_id in entity_id_list:
    entity_info = result_map.get(entity_id)
    if entity_info:
        ordered_list.append(entity_info)

Dictionary lookup provides O(1) lookups with minimal overhead. This ensures the returned list matches the caller's original sequence while keeping recovery cost negligible.

4. Slimming the Response Payload

Examining original response fields revealed structural issues:

We pruned the response to the essential minimum:

Field reduction delivered direct gains:

Performance Results

Combined optimizations produced measurable improvement:

Metric Before After
Mean response time >1000ms <300ms
High-concurrency throughput Low (frequent timeouts) High (stable)
Data transfer size Large Small
System resource usage High Noticeably reduced

Load-testing and APM monitoring (Pinpoint) confirmed that end-to-end latency curves shifted downward across the board, with anomalous spikes significantly reduced.

Observations

This optimization demonstrates four inseparable components working together:

  1. Database Access Patterns—Batch queries vastly outperform iterative ones; this is the primary lever for reducing database pressure under concurrency.
  2. Database Views—Pre-joining complex multi-table logic simplifies interface code and makes future maintenance straightforward.
  3. Application-Layer Ordering—Batch results lack guaranteed order and require explicit handling in the application to preserve caller expectations.
  4. Field Reduction—Eliminating redundant and unused fields directly lowers transmission cost, with outsized gains in high-concurrency scenarios.

This optimization pattern originated with location queries but applies equally to any API facing high concurrency and large data volumes.

© 2026 Yuxu Ge ·