Mysql solves the database N+1 query problem

Mysql solves the database N+1 query problem

Introduction

In orm frameworks, such as hibernate and mybatis, you can set associated objects, such as user objects associated with dept
If n users are found, then n dept queries are needed. Querying a user is a select operation, and querying the user's related
dept, is n times, so it is an n+1 problem, but it is more reasonable to call it 1+n.

mybatis configuration

UserMapper.xml

<resultMap id="BaseResultMap" type="testmaven.entity.User">
  <id column="id" jdbcType="INTEGER" property="id" />
  <result column="name" jdbcType="VARCHAR" property="name" />
  <result column="age" jdbcType="INTEGER" property="age" />
  <result column="dept_id" jdbcType="INTEGER" property="deptId" />
  <association property="dept" column="dept_id" fetchType="eager" select="testmaven.mapper.DeptMapper.selectByPrimaryKey" ></association>
 </resultMap>

The data table is as follows:

department table

|id|name|

User Table

|id|name|department_id|

The requirement is to get data with the following structure:

[
  { "id":1, "name":"test", "department_id":1, "department":{ "id":1, "name":"Test Department"
    }
  }
]

Method 1: Loop query

Query user list

Circular user list to query the corresponding department information

$users = $db->query('SELECT * FROM `user`'); foreach($users as &$user) {
  $users['department'] = $db->query('SELECT * FROM `department` WHERE `id` = '.$user['department_id']);
}

This method performs 1+N queries (1 query to the list, N queries to the department), which has the lowest performance and is not advisable.

Method 2: Join Tables

Query user and department data through joined tables

Processing returned data

$users = $db->query('SELECT * FROM `user` INNER JOIN `department` ON `department`.`id` = `user`.`department_id`'); // Manual processing returns the result as required structure

This method actually has limitations. If the user and department are not on the same server, the tables cannot be joined.

Method 3: 1+1 query

This method first queries the user list once

Take out the department ID in the list to form an array

Query the department in step 2

Merge final data

The code is roughly as follows:

$users = $db->query('SELECT * FROM `user`');
$departmentIds = [ ]; foreach($users as $user) { if(!in_array($user['department_id'], $departmentIds)) {
    $departmentIds[] = $user['department_id'];
  }
}
$departments = $db->query('SELECT * FROM `department` WHERE id in ('.join(',',$department_id).')');
$map = []; // [department ID => department item]foreach($departments as $department) {
  $map[$department['id']] = $department;
}foreach($users as $user) {
  $user['department'] = $map[$user['department_id']] ?? null;
 }

This method has no restrictions on the two tables and is a better approach given the current popularity of microservices.

You may also be interested in:
  • SQL query for users who have logged in for at least n consecutive days
  • MySQL gets the first N records of all categories
  • How to find numbers that appear more than n times in a row in mysql

<<:  How to implement property hijacking with JavaScript defineProperty

>>:  Implementation steps for building a local web server on Centos8

Recommend

Solve nginx "504 Gateway Time-out" error

Students who make websites often find that some n...

Implementation of Docker data volume operations

Getting Started with Data Volumes In the previous...

MySQL database operation and maintenance data recovery method

The previous three articles introduced common bac...

Nginx/Httpd reverse proxy tomcat configuration tutorial

In the previous blog, we learned about the usage ...

Element UI table realizes drop-down filtering function

This article example shares the specific code for...

Linux sudo vulnerability could lead to unauthorized privileged access

Exploiting a newly discovered sudo vulnerability ...

Implementation of mysql data type conversion

1. Problem There is a table as shown below, we ne...

The principle and application of MySQL connection query

Overview One of the most powerful features of MyS...

How to use node scaffolding to build a server to implement token verification

content Use scaffolding to quickly build a node p...

Vue implements simple comment function

This article shares the specific code of Vue to i...

CSS hacks \9 and \0 may not work for hacking IE11\IE9\IE8

Every time I design a web page or a form, I am tr...

Solution to the failure of docker windows10 shared directory mounting

cause When executing the docker script, an error ...

Share MySql8.0.19 installation pit record

The previous article introduced the installation ...