...

>

Design Considerations of Yelp

Design Considerations of Yelp

Discover how to design a highly scalable proximity service like Yelp by addressing core challenges such as searching and data partitioning. Implement dynamic segmentation and QuadTrees for efficient spatial indexing. Evaluate the final System Design against non-functional requirements like availability and performance.

Introduction

The previous lesson covered the system architecture, core components, and overall workflow, which raised several open design questions. For example, how should the system retrieve nearby places, and how should it rank them by popularity? This lesson addresses these design concerns. The following table summarizes the objectives of this lesson.

Summary of the Lesson

Section/Sub-section

Purpose

Searching

This process divides the world into segments to optimize the search, so that all nearby sites in a given location and radius can be identified.

Storing Indexes

We index the places to improve query performance and estimate the storage required for all of the indexes.

Searching Using Segments

We search all the desired places by combining the segments.

Dynamic Segments

We solve the static segment limitations using dynamic segments.

Searching Using a QuadTree

We explore the searching functionality using a QuadTree.

Space Estimations for a QuadTree

We estimate the storage required for a QuadTree.

Data Partitioning

We look into the options we can use to partition data.

Ensuring Availability

We look into how we’ll ensure the availability of the system.

Inserting a New Place

We look into how we’ll insert the place in a QuadTree.

Ranking Popular Places

We rank the places of the system.

Evaluation

We evaluate how our system fulfills the non-functional requirements.

Searching

Using Google Maps, we were able to connect segments and overcome the scalability challenge to efficiently process a large graph. The graph of the world had numerous nodes and vertices, and traversing them was time-consuming. Therefore, we divided the whole world into smaller segments/subgraphs to process and query them simultaneously. The segmentation helps improve the system’s scalability.

Each segment will be of the size 5×5 miles5 \times 5 \ \text{miles} and will contain a list of places that exist within it. We only search a few segments to find nearby destinations. We can use a given location and a defined radius to find all nearby segments and identify nearby sites.

Partitioning the globe into small segments, where each segment has four coordinates (lat, long) and all segments hold the coordinates of different places
Partitioning the globe into small segments, where each segment has four coordinates (lat, long) and all segments hold the coordinates of different places
1.

How will we find nearby places if we create a table for storing all places?

Show Answer
1 / 2

We can store all the places in a table and uniquely identify a segment by having a segment_ID. We can index each segment in the database. Now, we have limited the number of segments we need to search, so the query will be optimized and return results quickly.

Improve data fetching

We use a key-value store for quick access to places in the segments. The key is the segment_ID, while the value contains the list of places in that segment. Let’s estimate how much space we need to store the indexes.

We can usually store a few MBs in the value of the key-value store. If we assume that each segment has 500 places then it will take up 500×1296 Bytes = 0.648MB500 \times 1296 \ \text{Bytes = 0.648MB}, and we can easily store it as a value.

The total area of the Earth is around 200 million square miles, and the land surface area is about 60 million square miles. If we assume our radius is 10 miles, we’ll have 6 million segments. An 8-byte identifier will identify each segment.

Let’s calculate how much memory we need.

Total Area of the Earth (Million Square Miles)60
Search Radius (Miles)10
Number of Segments (Millions)f6
Segment_ID (Bytes)8
Place_ID (Bytes)8
Number of Places (Millions)500
Total Space (GB)f4.048

Search using segments

A user may select a radius to search for places that aren’t in a single segment. So, we need to combine multiple segments by connecting the segments to find locations within the specified radius—say, 5 miles.

First, we constrain the number of segments. This reduces the graph size and enables the search process to be optimized. Then, we identify all relevant locations, compute the distance to the search point, and display it to the user.

Searching for locations using segments
Searching for locations using segments
1.

Can you identify a problem with the current approach?

Show Answer
Did you find this helpful?

Dynamic segments

We solve the problem of uneven distribution of places in a segment by dynamically sizing the segments. We do this by focusing on the number of places. We split a segment into four more segments if the number of places reaches a certain limit. We assume 500 places as our limit. While using this approach, we need to decide on the following questions:

  1. How will we map the segments?

  2. How will we connect to other segments?

We use a QuadTreeA QuadTree is a tree data structure in which each internal node has exactly four children. QuadTrees are the two-dimensional analog of octrees and are most often used to partition a two-dimensional space by recursively subdividing it into four quadrants or regions. The data associated with a leaf cell varies by application, but the leaf cell represents a “unit of interesting spatial information”. Source: Wikipedia to manage our segments. Each node contains the information of a segment. If the number of places exceeds 500, we split the segment into four additional child nodes and divide the places among them. In this way, the leaf nodes will be those segments that can’t be broken down any further. Each leaf node will have a list of places in it, too.

Search using a QuadTree

We start at the root node and continue visiting nodes to find the desired segment. We check every node to see if it has more child nodes. If a node has no more children, then we stop our search because that node is the required one. We also connect each child node to its neighbors using a doubly linked list. All child nodes of all parent nodes are connected via a doubly linked list. This list allows us to find the neighboring segments when we need to move forward or backward, as per our requirements. After identifying the segments, we have the required PlaceID values of the places, and we can search our ...