sql-explain-query
sql-explain-query
price,
shop_products.uploaded_media from shop_products where exists (select * from
shop_categories inner join shop_category_product on shop_categories.id =
shop_category_product.shop_category_id where shop_products.id =
shop_category_product.shop_product_id and shop_categories.id in
('01j6m3fwxa2bqsy5te710k696q') and shop_categories.deleted_at is null) and
shop_products.deleted_at is null order by id desc limit 10 offset 0 \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: shop_categories
partitions: NULL
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 104
ref: const
rows: 1
filtered: 100.00
Extra: Using temporary; Using filesort
*************************** 2. row ***************************
id: 1
select_type: SIMPLE
table: shop_category_product
partitions: NULL
type: ref
possible_keys:
shop_category_product_shop_category_id_foreign,shop_category_product_shop_product_i
d_foreign
key: shop_category_product_shop_category_id_foreign
key_len: 104
ref: const
rows: 3
filtered: 100.00
Extra: Using index condition; Start temporary
*************************** 3. row ***************************
id: 1
select_type: SIMPLE
table: shop_products
partitions: NULL
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 104
ref: xyz.shop_category_product.shop_product_id
rows: 1
filtered: 10.00
Extra: Using where; End temporary
ChatGPT said:
ChatGPT
The EXPLAIN output you provided breaks down how your SQL query is executed by the
database, showing the order in which tables are accessed, the type of joins used,
and other relevant details. Let’s walk through each row of the EXPLAIN output to
understand what’s happening.
Query Recap
You are selecting products from shop_products where a related category exists in
shop_categories (based on the shop_category_product join table). The query also
ensures that the selected categories are not soft-deleted (using deleted_at).
Explanation of Each Row
1. First Row:
plaintext
Copy code
id: 1
select_type: SIMPLE
table: shop_categories
partitions: NULL
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 104
ref: const
rows: 1
filtered: 100.00
Extra: Using temporary; Using filesort
Table: shop_categories
Type: const
Indicates that the query is looking up a single value in the shop_categories table,
using a constant (likely because the IN clause only has one value).
Key: PRIMARY
The query uses the primary key of shop_categories for this lookup.
Rows: 1
The query engine expects to examine only one row in the shop_categories table.
Filtered: 100.00
This means that all rows that are matched will be included in the result set.
Extra: Using temporary; Using filesort
A temporary table is being used, and the result set is being sorted using a
filesort (which means sorting is not done in memory but on disk).
2. Second Row:
plaintext
Copy code
id: 1
select_type: SIMPLE
table: shop_category_product
partitions: NULL
type: ref
possible_keys:
shop_category_product_shop_category_id_foreign,shop_category_product_shop_product_i
d_foreign
key: shop_category_product_shop_category_id_foreign
key_len: 104
ref: const
rows: 3
filtered: 100.00
Extra: Using index condition; Start temporary
Table: shop_category_product
Type: ref
The join is performed by a non-unique index scan, meaning it’s using a foreign key
to match rows in shop_category_product.
Key: shop_category_product_shop_category_id_foreign
This is the index used to perform the join on shop_category_product.
Rows: 3
The query engine estimates that it will find 3 matching rows in
shop_category_product.
Filtered: 100.00
All rows that match the condition will be processed.
Extra: Using index condition; Start temporary
The Using index condition suggests that an index condition is being applied to
filter rows, and the Start temporary indicates that this is part of building the
temporary result set.
3. Third Row:
plaintext
Copy code
id: 1
select_type: SIMPLE
table: shop_products
partitions: NULL
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 104
ref: xyz.shop_category_product.shop_product_id
rows: 1
filtered: 10.00
Extra: Using where; End temporary
Table: shop_products
Type: eq_ref
This is a highly efficient join type where the query matches exactly one row in
shop_products for each row in shop_category_product.
Key: PRIMARY
The query uses the primary key of shop_products to find the matching row.
Rows: 1
The query engine expects to find exactly one matching row in shop_products.
Filtered: 10.00
Only 10% of the rows will pass the filter condition (shop_products.deleted_at is
null).
Extra: Using where; End temporary
The Using where indicates that a filter is applied to the rows, and End temporary
signifies the end of processing for the temporary result set.
Summary
Step 1: The query first checks the shop_categories table using the primary key and
the given category ID (const lookup).
Step 2: It then moves to the shop_category_product table, joining on the foreign
key that links categories to products.
Step 3: Finally, it retrieves the relevant rows from shop_products using an
efficient primary key lookup, applying the where condition to filter out soft-
deleted products.
The EXPLAIN output provides insights into the efficiency of each step, the use of
indexes, and whether any operations require more resource-intensive processing like
sorting or using temporary tables.