MYSQL Proper columns indexing
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ margin-bottom:0;
}
I've the following products
table
CREATE TABLE `tmp_products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
`brand_id` int(11) NOT NULL,
`store_id` int(11) NOT NULL,
`title` varchar(250) NOT NULL,
`price` decimal(10,0) NOT NULL,
`sale_price` decimal(10,0) NOT NULL,
`discount_value` decimal(10,0) NOT NULL,
`discount_percentage` decimal(10,0) NOT NULL,
`color` varchar(64) NOT NULL,
`size` varchar(64) NOT NULL,
`weight` decimal(10,0) NOT NULL,
`image` text NOT NULL,
`fast_shipping` tinyint(1) NOT NULL,
PRIMARY KEY (`id`),
KEY `parent_id` (`parent_id`),
KEY `category_id` (`category_id`),
KEY `brand_id` (`brand_id`),
KEY `sale_price` (`sale_price`),
KEY `discount_percentage` (`discount_percentage`),
KEY `color` (`color`),
KEY `size` (`size`),
KEY `weight` (`weight`),
KEY `store_id` (`store_id`),
KEY `fast_shipping` (`fast_shipping`),
FULLTEXT KEY `title` (`title`)
) ENGINE=InnoDB
And there is another product_categories
table
CREATE TABLE `product_categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `product_id` (`product_id`),
KEY `category_id` (`category_id`)
) ENGINE=InnoDB
I may filter the data with any of the previous columns in the products
table and all of it is or/and
clause based on customer filtration like:
category_id
: is joined with the product_categories
if the customer hits the category page
brand_id
could be used in the brand page or as a filter in search
or category
page.
sale_price
: could be used in filtering products.
title
: full text search index.
fast_shipping
: a flag with 0 and 1 values to indicate the products with fast shipping.
store_id
: mainly used to get info about the store that owns that product and and also is used to join with countries
table to get the store country.
Stores table has an indexed country_id
for countries table
Most of the above columns would be used also in ordering and the parent_id will be used if there is no filter by color and size.
The question here is there a better way to optimize my select query to make it faster as i'm dealing with some millions of products here.
So, do i've to use any compound indexes instead of single indexes to make my query faster?
Edit
Some samples of queries that may run based on customer filtration:
A query for fetching products for a table:
select `p`.`id`, `p`.`fast_shipping`, `p`.`category_id`, `p`.`weight`, `p`.`title`, `p`.`price`, `p`.`sale_price`, `p`.`discount_percentage`, `p`.`image`, `p`.`color`, `p`.`size`,
CONCAT(u.hash, "/", u.name) AS country_flag
from `products` as `p`
inner join `stores` as `s` on `s`.`id` = `p`.`store_id`
inner join `countries` as `c` on `c`.`id` = `s`.`country_id`
left join `uploads` as `u` on `u`.`id` = `c`.`flag`
where p.id IN (SELECT product_id FROM product_categories WHERE category_id = 395)
and `p`.`parent_id` = 0 order by `p`.`id` desc limit 36 offset 0
Query to add more filter by price
select `p`.`id`, `p`.`fast_shipping`, `p`.`category_id`, `p`.`weight`, `p`.`title`, `p`.`price`, `p`.`sale_price`, `p`.`discount_percentage`, `p`.`image`, `p`.`color`, `p`.`size`,
CONCAT(u.hash, "/", u.name) AS country_flag
from `products` as `p`
inner join `stores` as `s` on `s`.`id` = `p`.`store_id`
inner join `countries` as `c` on `c`.`id` = `s`.`country_id`
left join `uploads` as `u` on `u`.`id` = `c`.`flag`
where p.id IN (SELECT product_id FROM product_categories WHERE category_id = 395)
and `p`.`parent_id` = 0
and `p`.`sale_price` >= 20 and `p`.`sale_price` <= 120
order by p
.id
desc limit 36 offset 0
mysql
bumped to the homepage by Community♦ 3 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
I've the following products
table
CREATE TABLE `tmp_products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
`brand_id` int(11) NOT NULL,
`store_id` int(11) NOT NULL,
`title` varchar(250) NOT NULL,
`price` decimal(10,0) NOT NULL,
`sale_price` decimal(10,0) NOT NULL,
`discount_value` decimal(10,0) NOT NULL,
`discount_percentage` decimal(10,0) NOT NULL,
`color` varchar(64) NOT NULL,
`size` varchar(64) NOT NULL,
`weight` decimal(10,0) NOT NULL,
`image` text NOT NULL,
`fast_shipping` tinyint(1) NOT NULL,
PRIMARY KEY (`id`),
KEY `parent_id` (`parent_id`),
KEY `category_id` (`category_id`),
KEY `brand_id` (`brand_id`),
KEY `sale_price` (`sale_price`),
KEY `discount_percentage` (`discount_percentage`),
KEY `color` (`color`),
KEY `size` (`size`),
KEY `weight` (`weight`),
KEY `store_id` (`store_id`),
KEY `fast_shipping` (`fast_shipping`),
FULLTEXT KEY `title` (`title`)
) ENGINE=InnoDB
And there is another product_categories
table
CREATE TABLE `product_categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `product_id` (`product_id`),
KEY `category_id` (`category_id`)
) ENGINE=InnoDB
I may filter the data with any of the previous columns in the products
table and all of it is or/and
clause based on customer filtration like:
category_id
: is joined with the product_categories
if the customer hits the category page
brand_id
could be used in the brand page or as a filter in search
or category
page.
sale_price
: could be used in filtering products.
title
: full text search index.
fast_shipping
: a flag with 0 and 1 values to indicate the products with fast shipping.
store_id
: mainly used to get info about the store that owns that product and and also is used to join with countries
table to get the store country.
Stores table has an indexed country_id
for countries table
Most of the above columns would be used also in ordering and the parent_id will be used if there is no filter by color and size.
The question here is there a better way to optimize my select query to make it faster as i'm dealing with some millions of products here.
So, do i've to use any compound indexes instead of single indexes to make my query faster?
Edit
Some samples of queries that may run based on customer filtration:
A query for fetching products for a table:
select `p`.`id`, `p`.`fast_shipping`, `p`.`category_id`, `p`.`weight`, `p`.`title`, `p`.`price`, `p`.`sale_price`, `p`.`discount_percentage`, `p`.`image`, `p`.`color`, `p`.`size`,
CONCAT(u.hash, "/", u.name) AS country_flag
from `products` as `p`
inner join `stores` as `s` on `s`.`id` = `p`.`store_id`
inner join `countries` as `c` on `c`.`id` = `s`.`country_id`
left join `uploads` as `u` on `u`.`id` = `c`.`flag`
where p.id IN (SELECT product_id FROM product_categories WHERE category_id = 395)
and `p`.`parent_id` = 0 order by `p`.`id` desc limit 36 offset 0
Query to add more filter by price
select `p`.`id`, `p`.`fast_shipping`, `p`.`category_id`, `p`.`weight`, `p`.`title`, `p`.`price`, `p`.`sale_price`, `p`.`discount_percentage`, `p`.`image`, `p`.`color`, `p`.`size`,
CONCAT(u.hash, "/", u.name) AS country_flag
from `products` as `p`
inner join `stores` as `s` on `s`.`id` = `p`.`store_id`
inner join `countries` as `c` on `c`.`id` = `s`.`country_id`
left join `uploads` as `u` on `u`.`id` = `c`.`flag`
where p.id IN (SELECT product_id FROM product_categories WHERE category_id = 395)
and `p`.`parent_id` = 0
and `p`.`sale_price` >= 20 and `p`.`sale_price` <= 120
order by p
.id
desc limit 36 offset 0
mysql
bumped to the homepage by Community♦ 3 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
I've the following products
table
CREATE TABLE `tmp_products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
`brand_id` int(11) NOT NULL,
`store_id` int(11) NOT NULL,
`title` varchar(250) NOT NULL,
`price` decimal(10,0) NOT NULL,
`sale_price` decimal(10,0) NOT NULL,
`discount_value` decimal(10,0) NOT NULL,
`discount_percentage` decimal(10,0) NOT NULL,
`color` varchar(64) NOT NULL,
`size` varchar(64) NOT NULL,
`weight` decimal(10,0) NOT NULL,
`image` text NOT NULL,
`fast_shipping` tinyint(1) NOT NULL,
PRIMARY KEY (`id`),
KEY `parent_id` (`parent_id`),
KEY `category_id` (`category_id`),
KEY `brand_id` (`brand_id`),
KEY `sale_price` (`sale_price`),
KEY `discount_percentage` (`discount_percentage`),
KEY `color` (`color`),
KEY `size` (`size`),
KEY `weight` (`weight`),
KEY `store_id` (`store_id`),
KEY `fast_shipping` (`fast_shipping`),
FULLTEXT KEY `title` (`title`)
) ENGINE=InnoDB
And there is another product_categories
table
CREATE TABLE `product_categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `product_id` (`product_id`),
KEY `category_id` (`category_id`)
) ENGINE=InnoDB
I may filter the data with any of the previous columns in the products
table and all of it is or/and
clause based on customer filtration like:
category_id
: is joined with the product_categories
if the customer hits the category page
brand_id
could be used in the brand page or as a filter in search
or category
page.
sale_price
: could be used in filtering products.
title
: full text search index.
fast_shipping
: a flag with 0 and 1 values to indicate the products with fast shipping.
store_id
: mainly used to get info about the store that owns that product and and also is used to join with countries
table to get the store country.
Stores table has an indexed country_id
for countries table
Most of the above columns would be used also in ordering and the parent_id will be used if there is no filter by color and size.
The question here is there a better way to optimize my select query to make it faster as i'm dealing with some millions of products here.
So, do i've to use any compound indexes instead of single indexes to make my query faster?
Edit
Some samples of queries that may run based on customer filtration:
A query for fetching products for a table:
select `p`.`id`, `p`.`fast_shipping`, `p`.`category_id`, `p`.`weight`, `p`.`title`, `p`.`price`, `p`.`sale_price`, `p`.`discount_percentage`, `p`.`image`, `p`.`color`, `p`.`size`,
CONCAT(u.hash, "/", u.name) AS country_flag
from `products` as `p`
inner join `stores` as `s` on `s`.`id` = `p`.`store_id`
inner join `countries` as `c` on `c`.`id` = `s`.`country_id`
left join `uploads` as `u` on `u`.`id` = `c`.`flag`
where p.id IN (SELECT product_id FROM product_categories WHERE category_id = 395)
and `p`.`parent_id` = 0 order by `p`.`id` desc limit 36 offset 0
Query to add more filter by price
select `p`.`id`, `p`.`fast_shipping`, `p`.`category_id`, `p`.`weight`, `p`.`title`, `p`.`price`, `p`.`sale_price`, `p`.`discount_percentage`, `p`.`image`, `p`.`color`, `p`.`size`,
CONCAT(u.hash, "/", u.name) AS country_flag
from `products` as `p`
inner join `stores` as `s` on `s`.`id` = `p`.`store_id`
inner join `countries` as `c` on `c`.`id` = `s`.`country_id`
left join `uploads` as `u` on `u`.`id` = `c`.`flag`
where p.id IN (SELECT product_id FROM product_categories WHERE category_id = 395)
and `p`.`parent_id` = 0
and `p`.`sale_price` >= 20 and `p`.`sale_price` <= 120
order by p
.id
desc limit 36 offset 0
mysql
I've the following products
table
CREATE TABLE `tmp_products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
`brand_id` int(11) NOT NULL,
`store_id` int(11) NOT NULL,
`title` varchar(250) NOT NULL,
`price` decimal(10,0) NOT NULL,
`sale_price` decimal(10,0) NOT NULL,
`discount_value` decimal(10,0) NOT NULL,
`discount_percentage` decimal(10,0) NOT NULL,
`color` varchar(64) NOT NULL,
`size` varchar(64) NOT NULL,
`weight` decimal(10,0) NOT NULL,
`image` text NOT NULL,
`fast_shipping` tinyint(1) NOT NULL,
PRIMARY KEY (`id`),
KEY `parent_id` (`parent_id`),
KEY `category_id` (`category_id`),
KEY `brand_id` (`brand_id`),
KEY `sale_price` (`sale_price`),
KEY `discount_percentage` (`discount_percentage`),
KEY `color` (`color`),
KEY `size` (`size`),
KEY `weight` (`weight`),
KEY `store_id` (`store_id`),
KEY `fast_shipping` (`fast_shipping`),
FULLTEXT KEY `title` (`title`)
) ENGINE=InnoDB
And there is another product_categories
table
CREATE TABLE `product_categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `product_id` (`product_id`),
KEY `category_id` (`category_id`)
) ENGINE=InnoDB
I may filter the data with any of the previous columns in the products
table and all of it is or/and
clause based on customer filtration like:
category_id
: is joined with the product_categories
if the customer hits the category page
brand_id
could be used in the brand page or as a filter in search
or category
page.
sale_price
: could be used in filtering products.
title
: full text search index.
fast_shipping
: a flag with 0 and 1 values to indicate the products with fast shipping.
store_id
: mainly used to get info about the store that owns that product and and also is used to join with countries
table to get the store country.
Stores table has an indexed country_id
for countries table
Most of the above columns would be used also in ordering and the parent_id will be used if there is no filter by color and size.
The question here is there a better way to optimize my select query to make it faster as i'm dealing with some millions of products here.
So, do i've to use any compound indexes instead of single indexes to make my query faster?
Edit
Some samples of queries that may run based on customer filtration:
A query for fetching products for a table:
select `p`.`id`, `p`.`fast_shipping`, `p`.`category_id`, `p`.`weight`, `p`.`title`, `p`.`price`, `p`.`sale_price`, `p`.`discount_percentage`, `p`.`image`, `p`.`color`, `p`.`size`,
CONCAT(u.hash, "/", u.name) AS country_flag
from `products` as `p`
inner join `stores` as `s` on `s`.`id` = `p`.`store_id`
inner join `countries` as `c` on `c`.`id` = `s`.`country_id`
left join `uploads` as `u` on `u`.`id` = `c`.`flag`
where p.id IN (SELECT product_id FROM product_categories WHERE category_id = 395)
and `p`.`parent_id` = 0 order by `p`.`id` desc limit 36 offset 0
Query to add more filter by price
select `p`.`id`, `p`.`fast_shipping`, `p`.`category_id`, `p`.`weight`, `p`.`title`, `p`.`price`, `p`.`sale_price`, `p`.`discount_percentage`, `p`.`image`, `p`.`color`, `p`.`size`,
CONCAT(u.hash, "/", u.name) AS country_flag
from `products` as `p`
inner join `stores` as `s` on `s`.`id` = `p`.`store_id`
inner join `countries` as `c` on `c`.`id` = `s`.`country_id`
left join `uploads` as `u` on `u`.`id` = `c`.`flag`
where p.id IN (SELECT product_id FROM product_categories WHERE category_id = 395)
and `p`.`parent_id` = 0
and `p`.`sale_price` >= 20 and `p`.`sale_price` <= 120
order by p
.id
desc limit 36 offset 0
mysql
mysql
edited Jul 27 '18 at 10:58
Hasan Zohdy
asked Jul 27 '18 at 10:06
Hasan ZohdyHasan Zohdy
63
63
bumped to the homepage by Community♦ 3 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
bumped to the homepage by Community♦ 3 mins ago
This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
The question here is there a better way to optimize my select query to
make it faster as i'm dealing with some millions of products here.
well there isnt something called better way and it depends on every query, you didnt show us any queries.
you can use compound indexes when you have several column in where conditions, for example if you create index on (id,category_id,brand_id ) and where condition you have only id, category_id
, the index will be used.
I've edited my question.
– Hasan Zohdy
Jul 27 '18 at 10:58
well the query is taking time ? how much data are there in the tables ? you can create index on (id,flag) and (id,country_id)
– moudiz
Jul 27 '18 at 11:16
There is already indexes for each column..separately but not compound ones. There is about 2.5m products and query takes about 2-4 seconds.
– Hasan Zohdy
Jul 27 '18 at 11:20
The query will read one index , you can get the query plan for the query and check which index is reading and its cost. anyway in your scenario you can add a compound index. the best way to make sure is to test it @HasanZohdy
– moudiz
Jul 27 '18 at 11:25
add a comment |
The first thing is to rid of the IN
clause and the subselect. Both of them can be replaced by single JOIN
:
SELECT p.id
, p.fast_shipping
, p.category_id
, p.weight
, p.title
, p.price
, p.sale_price
, p.discount_percentage
, p.image
, p.color
, p.size
, CONCAT(u.hash, "/", u.name) AS country_flag
FROM products AS p
-- Here is the replacement for "IN (SELECT.." and "WHERE"
-- It's placed immediately after the `products` table to reduce the derived table size
JOIN product_categories AS pc ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
-- All the rest JOINs. `INNER JOIN..ON` is the same as `JOIN..ON` for mysql.
JOIN stores AS s ON s.id = p.store_id
JOIN countries AS c ON c.id = s.country_id
LEFT JOIN uploads AS u ON u.id = c.flag
-- WHERE is trimmed out completely
ORDER BY p.id DESC
LIMIT 36 OFFSET 0
;
For the given query you need the next multicolumn indexes:
- table
products
- (parent_id, store_id) - table
product_categories
- (product_id, category_id) - table
stores
- (id, country_id) but simple (country_id) is enough ifid
is the PK forstores
table
The second query can be modified the same way, except the products
table now need an index (parent_id, store_id, sale_price)
:
SELECT p.id
, p.fast_shipping
, p.category_id
, p.weight
, p.title
, p.price
, p.sale_price
, p.discount_percentage
, p.image
, p.color
, p.size
, CONCAT(u.hash, "/", u.name) AS country_flag
FROM products AS p
JOIN product_categories AS pc ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
AND p.sale_price BETWEEN 20 AND 120
JOIN stores AS s ON s.id = p.store_id
JOIN countries AS c ON c.id = s.country_id
LEFT JOIN uploads AS u ON u.id = c.flag
;
As far as (parent_id, store_id, sale_price)
index can replace the (parent_id, store_id)
one you need only (parent_id, store_id, sale_price)
, not both.
Thanks for the great answer, but what if there is a search bycolor
and/orsize
, also discount_percentage may or may not be used for filtering info, same applies onfast_shipping
– Hasan Zohdy
Jul 27 '18 at 21:38
In general, all the columns mentioned in the JOIN..ON / WHERE / GROUP BY / ORDER BY / etc should be indexed. If more than one column from the same table is involved all of them should be present in the multicolumn index. The bad news is that order columns are used for index is very significant. Three columns can be arranged in 6 ways. Four columns - in 24 ways. And so forth - factorial (n!). And there is no common rules to determine which order is the best. Even worst - different queries can require the different indexes - (a,b,c) and (c,a,b) for example.
– Kondybas
Jul 27 '18 at 22:00
So should i add more composite indexes for each combination? For now i've only single indexes for each column and i'm placing the conditions in a certain order based on customer filtration but the issue here is that i should do more indexes based on the given filter combinations, right?
– Hasan Zohdy
Jul 27 '18 at 22:15
Each extra index has an overhead. On the everyINSERT/UPDATE/DELETE
all related indexes should be updated. Also each index consumes the disk space and RAM that can drive to the overall slowdown. We can't create all possible indexes for each occasion. All that we can do is to restrict queries to some subset covered by indexes. Where is the balance depends on certain project.
– Kondybas
Jul 27 '18 at 22:31
The other three query types won't be the problem as i know the indexes will affect them, so i will just have to stick with single indexes now as best solution?
– Hasan Zohdy
Jul 27 '18 at 23:12
|
show 3 more comments
Please clean up the tables. product_categories
with product_id
and category_id
implies a many:many mapping between products and categories.
But the existence of category_id
in tmp_products
implies that a product belongs to only one category. This contradicts the many:many concept.
Which is it? Maybe tmp_products
needs main_category_id
? Or it is relation is not really many:many?
I also see parent_id
, which implies a hierarchy in tmp_products
. Is that correct? Is it relevant to this question?
As for 'proper indexing',...
This discusses optimal indexes for a many:many table (get rid of auto_inc; use composite PK, etc).- Do not index flags; such indexes won't be used due to poor cardinality.
- Learn to use "composite" indexes where appropriate.
- When using
MATCH
in theWHERE
clause of aSELECT
, theFULLTEXT
index will be the only index used.
Assuming
ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
AND p.sale_price BETWEEN 20 AND 120
then have these composite indexes:
p: PRIMARY KEY(id) -- (already exists)
p: INDEX(parent_id, sale_price)
pc: INDEX(category_id, product_id) -- (as mentioned above)
This set of indexes will happen to work whether or not you include the sale_price
limitation. Caveat: If you have other filtering, other indexes may be needed.
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "182"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f213394%2fmysql-proper-columns-indexing%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
The question here is there a better way to optimize my select query to
make it faster as i'm dealing with some millions of products here.
well there isnt something called better way and it depends on every query, you didnt show us any queries.
you can use compound indexes when you have several column in where conditions, for example if you create index on (id,category_id,brand_id ) and where condition you have only id, category_id
, the index will be used.
I've edited my question.
– Hasan Zohdy
Jul 27 '18 at 10:58
well the query is taking time ? how much data are there in the tables ? you can create index on (id,flag) and (id,country_id)
– moudiz
Jul 27 '18 at 11:16
There is already indexes for each column..separately but not compound ones. There is about 2.5m products and query takes about 2-4 seconds.
– Hasan Zohdy
Jul 27 '18 at 11:20
The query will read one index , you can get the query plan for the query and check which index is reading and its cost. anyway in your scenario you can add a compound index. the best way to make sure is to test it @HasanZohdy
– moudiz
Jul 27 '18 at 11:25
add a comment |
The question here is there a better way to optimize my select query to
make it faster as i'm dealing with some millions of products here.
well there isnt something called better way and it depends on every query, you didnt show us any queries.
you can use compound indexes when you have several column in where conditions, for example if you create index on (id,category_id,brand_id ) and where condition you have only id, category_id
, the index will be used.
I've edited my question.
– Hasan Zohdy
Jul 27 '18 at 10:58
well the query is taking time ? how much data are there in the tables ? you can create index on (id,flag) and (id,country_id)
– moudiz
Jul 27 '18 at 11:16
There is already indexes for each column..separately but not compound ones. There is about 2.5m products and query takes about 2-4 seconds.
– Hasan Zohdy
Jul 27 '18 at 11:20
The query will read one index , you can get the query plan for the query and check which index is reading and its cost. anyway in your scenario you can add a compound index. the best way to make sure is to test it @HasanZohdy
– moudiz
Jul 27 '18 at 11:25
add a comment |
The question here is there a better way to optimize my select query to
make it faster as i'm dealing with some millions of products here.
well there isnt something called better way and it depends on every query, you didnt show us any queries.
you can use compound indexes when you have several column in where conditions, for example if you create index on (id,category_id,brand_id ) and where condition you have only id, category_id
, the index will be used.
The question here is there a better way to optimize my select query to
make it faster as i'm dealing with some millions of products here.
well there isnt something called better way and it depends on every query, you didnt show us any queries.
you can use compound indexes when you have several column in where conditions, for example if you create index on (id,category_id,brand_id ) and where condition you have only id, category_id
, the index will be used.
answered Jul 27 '18 at 10:46
moudizmoudiz
1036
1036
I've edited my question.
– Hasan Zohdy
Jul 27 '18 at 10:58
well the query is taking time ? how much data are there in the tables ? you can create index on (id,flag) and (id,country_id)
– moudiz
Jul 27 '18 at 11:16
There is already indexes for each column..separately but not compound ones. There is about 2.5m products and query takes about 2-4 seconds.
– Hasan Zohdy
Jul 27 '18 at 11:20
The query will read one index , you can get the query plan for the query and check which index is reading and its cost. anyway in your scenario you can add a compound index. the best way to make sure is to test it @HasanZohdy
– moudiz
Jul 27 '18 at 11:25
add a comment |
I've edited my question.
– Hasan Zohdy
Jul 27 '18 at 10:58
well the query is taking time ? how much data are there in the tables ? you can create index on (id,flag) and (id,country_id)
– moudiz
Jul 27 '18 at 11:16
There is already indexes for each column..separately but not compound ones. There is about 2.5m products and query takes about 2-4 seconds.
– Hasan Zohdy
Jul 27 '18 at 11:20
The query will read one index , you can get the query plan for the query and check which index is reading and its cost. anyway in your scenario you can add a compound index. the best way to make sure is to test it @HasanZohdy
– moudiz
Jul 27 '18 at 11:25
I've edited my question.
– Hasan Zohdy
Jul 27 '18 at 10:58
I've edited my question.
– Hasan Zohdy
Jul 27 '18 at 10:58
well the query is taking time ? how much data are there in the tables ? you can create index on (id,flag) and (id,country_id)
– moudiz
Jul 27 '18 at 11:16
well the query is taking time ? how much data are there in the tables ? you can create index on (id,flag) and (id,country_id)
– moudiz
Jul 27 '18 at 11:16
There is already indexes for each column..separately but not compound ones. There is about 2.5m products and query takes about 2-4 seconds.
– Hasan Zohdy
Jul 27 '18 at 11:20
There is already indexes for each column..separately but not compound ones. There is about 2.5m products and query takes about 2-4 seconds.
– Hasan Zohdy
Jul 27 '18 at 11:20
The query will read one index , you can get the query plan for the query and check which index is reading and its cost. anyway in your scenario you can add a compound index. the best way to make sure is to test it @HasanZohdy
– moudiz
Jul 27 '18 at 11:25
The query will read one index , you can get the query plan for the query and check which index is reading and its cost. anyway in your scenario you can add a compound index. the best way to make sure is to test it @HasanZohdy
– moudiz
Jul 27 '18 at 11:25
add a comment |
The first thing is to rid of the IN
clause and the subselect. Both of them can be replaced by single JOIN
:
SELECT p.id
, p.fast_shipping
, p.category_id
, p.weight
, p.title
, p.price
, p.sale_price
, p.discount_percentage
, p.image
, p.color
, p.size
, CONCAT(u.hash, "/", u.name) AS country_flag
FROM products AS p
-- Here is the replacement for "IN (SELECT.." and "WHERE"
-- It's placed immediately after the `products` table to reduce the derived table size
JOIN product_categories AS pc ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
-- All the rest JOINs. `INNER JOIN..ON` is the same as `JOIN..ON` for mysql.
JOIN stores AS s ON s.id = p.store_id
JOIN countries AS c ON c.id = s.country_id
LEFT JOIN uploads AS u ON u.id = c.flag
-- WHERE is trimmed out completely
ORDER BY p.id DESC
LIMIT 36 OFFSET 0
;
For the given query you need the next multicolumn indexes:
- table
products
- (parent_id, store_id) - table
product_categories
- (product_id, category_id) - table
stores
- (id, country_id) but simple (country_id) is enough ifid
is the PK forstores
table
The second query can be modified the same way, except the products
table now need an index (parent_id, store_id, sale_price)
:
SELECT p.id
, p.fast_shipping
, p.category_id
, p.weight
, p.title
, p.price
, p.sale_price
, p.discount_percentage
, p.image
, p.color
, p.size
, CONCAT(u.hash, "/", u.name) AS country_flag
FROM products AS p
JOIN product_categories AS pc ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
AND p.sale_price BETWEEN 20 AND 120
JOIN stores AS s ON s.id = p.store_id
JOIN countries AS c ON c.id = s.country_id
LEFT JOIN uploads AS u ON u.id = c.flag
;
As far as (parent_id, store_id, sale_price)
index can replace the (parent_id, store_id)
one you need only (parent_id, store_id, sale_price)
, not both.
Thanks for the great answer, but what if there is a search bycolor
and/orsize
, also discount_percentage may or may not be used for filtering info, same applies onfast_shipping
– Hasan Zohdy
Jul 27 '18 at 21:38
In general, all the columns mentioned in the JOIN..ON / WHERE / GROUP BY / ORDER BY / etc should be indexed. If more than one column from the same table is involved all of them should be present in the multicolumn index. The bad news is that order columns are used for index is very significant. Three columns can be arranged in 6 ways. Four columns - in 24 ways. And so forth - factorial (n!). And there is no common rules to determine which order is the best. Even worst - different queries can require the different indexes - (a,b,c) and (c,a,b) for example.
– Kondybas
Jul 27 '18 at 22:00
So should i add more composite indexes for each combination? For now i've only single indexes for each column and i'm placing the conditions in a certain order based on customer filtration but the issue here is that i should do more indexes based on the given filter combinations, right?
– Hasan Zohdy
Jul 27 '18 at 22:15
Each extra index has an overhead. On the everyINSERT/UPDATE/DELETE
all related indexes should be updated. Also each index consumes the disk space and RAM that can drive to the overall slowdown. We can't create all possible indexes for each occasion. All that we can do is to restrict queries to some subset covered by indexes. Where is the balance depends on certain project.
– Kondybas
Jul 27 '18 at 22:31
The other three query types won't be the problem as i know the indexes will affect them, so i will just have to stick with single indexes now as best solution?
– Hasan Zohdy
Jul 27 '18 at 23:12
|
show 3 more comments
The first thing is to rid of the IN
clause and the subselect. Both of them can be replaced by single JOIN
:
SELECT p.id
, p.fast_shipping
, p.category_id
, p.weight
, p.title
, p.price
, p.sale_price
, p.discount_percentage
, p.image
, p.color
, p.size
, CONCAT(u.hash, "/", u.name) AS country_flag
FROM products AS p
-- Here is the replacement for "IN (SELECT.." and "WHERE"
-- It's placed immediately after the `products` table to reduce the derived table size
JOIN product_categories AS pc ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
-- All the rest JOINs. `INNER JOIN..ON` is the same as `JOIN..ON` for mysql.
JOIN stores AS s ON s.id = p.store_id
JOIN countries AS c ON c.id = s.country_id
LEFT JOIN uploads AS u ON u.id = c.flag
-- WHERE is trimmed out completely
ORDER BY p.id DESC
LIMIT 36 OFFSET 0
;
For the given query you need the next multicolumn indexes:
- table
products
- (parent_id, store_id) - table
product_categories
- (product_id, category_id) - table
stores
- (id, country_id) but simple (country_id) is enough ifid
is the PK forstores
table
The second query can be modified the same way, except the products
table now need an index (parent_id, store_id, sale_price)
:
SELECT p.id
, p.fast_shipping
, p.category_id
, p.weight
, p.title
, p.price
, p.sale_price
, p.discount_percentage
, p.image
, p.color
, p.size
, CONCAT(u.hash, "/", u.name) AS country_flag
FROM products AS p
JOIN product_categories AS pc ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
AND p.sale_price BETWEEN 20 AND 120
JOIN stores AS s ON s.id = p.store_id
JOIN countries AS c ON c.id = s.country_id
LEFT JOIN uploads AS u ON u.id = c.flag
;
As far as (parent_id, store_id, sale_price)
index can replace the (parent_id, store_id)
one you need only (parent_id, store_id, sale_price)
, not both.
Thanks for the great answer, but what if there is a search bycolor
and/orsize
, also discount_percentage may or may not be used for filtering info, same applies onfast_shipping
– Hasan Zohdy
Jul 27 '18 at 21:38
In general, all the columns mentioned in the JOIN..ON / WHERE / GROUP BY / ORDER BY / etc should be indexed. If more than one column from the same table is involved all of them should be present in the multicolumn index. The bad news is that order columns are used for index is very significant. Three columns can be arranged in 6 ways. Four columns - in 24 ways. And so forth - factorial (n!). And there is no common rules to determine which order is the best. Even worst - different queries can require the different indexes - (a,b,c) and (c,a,b) for example.
– Kondybas
Jul 27 '18 at 22:00
So should i add more composite indexes for each combination? For now i've only single indexes for each column and i'm placing the conditions in a certain order based on customer filtration but the issue here is that i should do more indexes based on the given filter combinations, right?
– Hasan Zohdy
Jul 27 '18 at 22:15
Each extra index has an overhead. On the everyINSERT/UPDATE/DELETE
all related indexes should be updated. Also each index consumes the disk space and RAM that can drive to the overall slowdown. We can't create all possible indexes for each occasion. All that we can do is to restrict queries to some subset covered by indexes. Where is the balance depends on certain project.
– Kondybas
Jul 27 '18 at 22:31
The other three query types won't be the problem as i know the indexes will affect them, so i will just have to stick with single indexes now as best solution?
– Hasan Zohdy
Jul 27 '18 at 23:12
|
show 3 more comments
The first thing is to rid of the IN
clause and the subselect. Both of them can be replaced by single JOIN
:
SELECT p.id
, p.fast_shipping
, p.category_id
, p.weight
, p.title
, p.price
, p.sale_price
, p.discount_percentage
, p.image
, p.color
, p.size
, CONCAT(u.hash, "/", u.name) AS country_flag
FROM products AS p
-- Here is the replacement for "IN (SELECT.." and "WHERE"
-- It's placed immediately after the `products` table to reduce the derived table size
JOIN product_categories AS pc ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
-- All the rest JOINs. `INNER JOIN..ON` is the same as `JOIN..ON` for mysql.
JOIN stores AS s ON s.id = p.store_id
JOIN countries AS c ON c.id = s.country_id
LEFT JOIN uploads AS u ON u.id = c.flag
-- WHERE is trimmed out completely
ORDER BY p.id DESC
LIMIT 36 OFFSET 0
;
For the given query you need the next multicolumn indexes:
- table
products
- (parent_id, store_id) - table
product_categories
- (product_id, category_id) - table
stores
- (id, country_id) but simple (country_id) is enough ifid
is the PK forstores
table
The second query can be modified the same way, except the products
table now need an index (parent_id, store_id, sale_price)
:
SELECT p.id
, p.fast_shipping
, p.category_id
, p.weight
, p.title
, p.price
, p.sale_price
, p.discount_percentage
, p.image
, p.color
, p.size
, CONCAT(u.hash, "/", u.name) AS country_flag
FROM products AS p
JOIN product_categories AS pc ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
AND p.sale_price BETWEEN 20 AND 120
JOIN stores AS s ON s.id = p.store_id
JOIN countries AS c ON c.id = s.country_id
LEFT JOIN uploads AS u ON u.id = c.flag
;
As far as (parent_id, store_id, sale_price)
index can replace the (parent_id, store_id)
one you need only (parent_id, store_id, sale_price)
, not both.
The first thing is to rid of the IN
clause and the subselect. Both of them can be replaced by single JOIN
:
SELECT p.id
, p.fast_shipping
, p.category_id
, p.weight
, p.title
, p.price
, p.sale_price
, p.discount_percentage
, p.image
, p.color
, p.size
, CONCAT(u.hash, "/", u.name) AS country_flag
FROM products AS p
-- Here is the replacement for "IN (SELECT.." and "WHERE"
-- It's placed immediately after the `products` table to reduce the derived table size
JOIN product_categories AS pc ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
-- All the rest JOINs. `INNER JOIN..ON` is the same as `JOIN..ON` for mysql.
JOIN stores AS s ON s.id = p.store_id
JOIN countries AS c ON c.id = s.country_id
LEFT JOIN uploads AS u ON u.id = c.flag
-- WHERE is trimmed out completely
ORDER BY p.id DESC
LIMIT 36 OFFSET 0
;
For the given query you need the next multicolumn indexes:
- table
products
- (parent_id, store_id) - table
product_categories
- (product_id, category_id) - table
stores
- (id, country_id) but simple (country_id) is enough ifid
is the PK forstores
table
The second query can be modified the same way, except the products
table now need an index (parent_id, store_id, sale_price)
:
SELECT p.id
, p.fast_shipping
, p.category_id
, p.weight
, p.title
, p.price
, p.sale_price
, p.discount_percentage
, p.image
, p.color
, p.size
, CONCAT(u.hash, "/", u.name) AS country_flag
FROM products AS p
JOIN product_categories AS pc ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
AND p.sale_price BETWEEN 20 AND 120
JOIN stores AS s ON s.id = p.store_id
JOIN countries AS c ON c.id = s.country_id
LEFT JOIN uploads AS u ON u.id = c.flag
;
As far as (parent_id, store_id, sale_price)
index can replace the (parent_id, store_id)
one you need only (parent_id, store_id, sale_price)
, not both.
edited Jul 27 '18 at 18:13
answered Jul 27 '18 at 17:53
KondybasKondybas
2,8711012
2,8711012
Thanks for the great answer, but what if there is a search bycolor
and/orsize
, also discount_percentage may or may not be used for filtering info, same applies onfast_shipping
– Hasan Zohdy
Jul 27 '18 at 21:38
In general, all the columns mentioned in the JOIN..ON / WHERE / GROUP BY / ORDER BY / etc should be indexed. If more than one column from the same table is involved all of them should be present in the multicolumn index. The bad news is that order columns are used for index is very significant. Three columns can be arranged in 6 ways. Four columns - in 24 ways. And so forth - factorial (n!). And there is no common rules to determine which order is the best. Even worst - different queries can require the different indexes - (a,b,c) and (c,a,b) for example.
– Kondybas
Jul 27 '18 at 22:00
So should i add more composite indexes for each combination? For now i've only single indexes for each column and i'm placing the conditions in a certain order based on customer filtration but the issue here is that i should do more indexes based on the given filter combinations, right?
– Hasan Zohdy
Jul 27 '18 at 22:15
Each extra index has an overhead. On the everyINSERT/UPDATE/DELETE
all related indexes should be updated. Also each index consumes the disk space and RAM that can drive to the overall slowdown. We can't create all possible indexes for each occasion. All that we can do is to restrict queries to some subset covered by indexes. Where is the balance depends on certain project.
– Kondybas
Jul 27 '18 at 22:31
The other three query types won't be the problem as i know the indexes will affect them, so i will just have to stick with single indexes now as best solution?
– Hasan Zohdy
Jul 27 '18 at 23:12
|
show 3 more comments
Thanks for the great answer, but what if there is a search bycolor
and/orsize
, also discount_percentage may or may not be used for filtering info, same applies onfast_shipping
– Hasan Zohdy
Jul 27 '18 at 21:38
In general, all the columns mentioned in the JOIN..ON / WHERE / GROUP BY / ORDER BY / etc should be indexed. If more than one column from the same table is involved all of them should be present in the multicolumn index. The bad news is that order columns are used for index is very significant. Three columns can be arranged in 6 ways. Four columns - in 24 ways. And so forth - factorial (n!). And there is no common rules to determine which order is the best. Even worst - different queries can require the different indexes - (a,b,c) and (c,a,b) for example.
– Kondybas
Jul 27 '18 at 22:00
So should i add more composite indexes for each combination? For now i've only single indexes for each column and i'm placing the conditions in a certain order based on customer filtration but the issue here is that i should do more indexes based on the given filter combinations, right?
– Hasan Zohdy
Jul 27 '18 at 22:15
Each extra index has an overhead. On the everyINSERT/UPDATE/DELETE
all related indexes should be updated. Also each index consumes the disk space and RAM that can drive to the overall slowdown. We can't create all possible indexes for each occasion. All that we can do is to restrict queries to some subset covered by indexes. Where is the balance depends on certain project.
– Kondybas
Jul 27 '18 at 22:31
The other three query types won't be the problem as i know the indexes will affect them, so i will just have to stick with single indexes now as best solution?
– Hasan Zohdy
Jul 27 '18 at 23:12
Thanks for the great answer, but what if there is a search by
color
and/or size
, also discount_percentage may or may not be used for filtering info, same applies on fast_shipping
– Hasan Zohdy
Jul 27 '18 at 21:38
Thanks for the great answer, but what if there is a search by
color
and/or size
, also discount_percentage may or may not be used for filtering info, same applies on fast_shipping
– Hasan Zohdy
Jul 27 '18 at 21:38
In general, all the columns mentioned in the JOIN..ON / WHERE / GROUP BY / ORDER BY / etc should be indexed. If more than one column from the same table is involved all of them should be present in the multicolumn index. The bad news is that order columns are used for index is very significant. Three columns can be arranged in 6 ways. Four columns - in 24 ways. And so forth - factorial (n!). And there is no common rules to determine which order is the best. Even worst - different queries can require the different indexes - (a,b,c) and (c,a,b) for example.
– Kondybas
Jul 27 '18 at 22:00
In general, all the columns mentioned in the JOIN..ON / WHERE / GROUP BY / ORDER BY / etc should be indexed. If more than one column from the same table is involved all of them should be present in the multicolumn index. The bad news is that order columns are used for index is very significant. Three columns can be arranged in 6 ways. Four columns - in 24 ways. And so forth - factorial (n!). And there is no common rules to determine which order is the best. Even worst - different queries can require the different indexes - (a,b,c) and (c,a,b) for example.
– Kondybas
Jul 27 '18 at 22:00
So should i add more composite indexes for each combination? For now i've only single indexes for each column and i'm placing the conditions in a certain order based on customer filtration but the issue here is that i should do more indexes based on the given filter combinations, right?
– Hasan Zohdy
Jul 27 '18 at 22:15
So should i add more composite indexes for each combination? For now i've only single indexes for each column and i'm placing the conditions in a certain order based on customer filtration but the issue here is that i should do more indexes based on the given filter combinations, right?
– Hasan Zohdy
Jul 27 '18 at 22:15
Each extra index has an overhead. On the every
INSERT/UPDATE/DELETE
all related indexes should be updated. Also each index consumes the disk space and RAM that can drive to the overall slowdown. We can't create all possible indexes for each occasion. All that we can do is to restrict queries to some subset covered by indexes. Where is the balance depends on certain project.– Kondybas
Jul 27 '18 at 22:31
Each extra index has an overhead. On the every
INSERT/UPDATE/DELETE
all related indexes should be updated. Also each index consumes the disk space and RAM that can drive to the overall slowdown. We can't create all possible indexes for each occasion. All that we can do is to restrict queries to some subset covered by indexes. Where is the balance depends on certain project.– Kondybas
Jul 27 '18 at 22:31
The other three query types won't be the problem as i know the indexes will affect them, so i will just have to stick with single indexes now as best solution?
– Hasan Zohdy
Jul 27 '18 at 23:12
The other three query types won't be the problem as i know the indexes will affect them, so i will just have to stick with single indexes now as best solution?
– Hasan Zohdy
Jul 27 '18 at 23:12
|
show 3 more comments
Please clean up the tables. product_categories
with product_id
and category_id
implies a many:many mapping between products and categories.
But the existence of category_id
in tmp_products
implies that a product belongs to only one category. This contradicts the many:many concept.
Which is it? Maybe tmp_products
needs main_category_id
? Or it is relation is not really many:many?
I also see parent_id
, which implies a hierarchy in tmp_products
. Is that correct? Is it relevant to this question?
As for 'proper indexing',...
This discusses optimal indexes for a many:many table (get rid of auto_inc; use composite PK, etc).- Do not index flags; such indexes won't be used due to poor cardinality.
- Learn to use "composite" indexes where appropriate.
- When using
MATCH
in theWHERE
clause of aSELECT
, theFULLTEXT
index will be the only index used.
Assuming
ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
AND p.sale_price BETWEEN 20 AND 120
then have these composite indexes:
p: PRIMARY KEY(id) -- (already exists)
p: INDEX(parent_id, sale_price)
pc: INDEX(category_id, product_id) -- (as mentioned above)
This set of indexes will happen to work whether or not you include the sale_price
limitation. Caveat: If you have other filtering, other indexes may be needed.
add a comment |
Please clean up the tables. product_categories
with product_id
and category_id
implies a many:many mapping between products and categories.
But the existence of category_id
in tmp_products
implies that a product belongs to only one category. This contradicts the many:many concept.
Which is it? Maybe tmp_products
needs main_category_id
? Or it is relation is not really many:many?
I also see parent_id
, which implies a hierarchy in tmp_products
. Is that correct? Is it relevant to this question?
As for 'proper indexing',...
This discusses optimal indexes for a many:many table (get rid of auto_inc; use composite PK, etc).- Do not index flags; such indexes won't be used due to poor cardinality.
- Learn to use "composite" indexes where appropriate.
- When using
MATCH
in theWHERE
clause of aSELECT
, theFULLTEXT
index will be the only index used.
Assuming
ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
AND p.sale_price BETWEEN 20 AND 120
then have these composite indexes:
p: PRIMARY KEY(id) -- (already exists)
p: INDEX(parent_id, sale_price)
pc: INDEX(category_id, product_id) -- (as mentioned above)
This set of indexes will happen to work whether or not you include the sale_price
limitation. Caveat: If you have other filtering, other indexes may be needed.
add a comment |
Please clean up the tables. product_categories
with product_id
and category_id
implies a many:many mapping between products and categories.
But the existence of category_id
in tmp_products
implies that a product belongs to only one category. This contradicts the many:many concept.
Which is it? Maybe tmp_products
needs main_category_id
? Or it is relation is not really many:many?
I also see parent_id
, which implies a hierarchy in tmp_products
. Is that correct? Is it relevant to this question?
As for 'proper indexing',...
This discusses optimal indexes for a many:many table (get rid of auto_inc; use composite PK, etc).- Do not index flags; such indexes won't be used due to poor cardinality.
- Learn to use "composite" indexes where appropriate.
- When using
MATCH
in theWHERE
clause of aSELECT
, theFULLTEXT
index will be the only index used.
Assuming
ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
AND p.sale_price BETWEEN 20 AND 120
then have these composite indexes:
p: PRIMARY KEY(id) -- (already exists)
p: INDEX(parent_id, sale_price)
pc: INDEX(category_id, product_id) -- (as mentioned above)
This set of indexes will happen to work whether or not you include the sale_price
limitation. Caveat: If you have other filtering, other indexes may be needed.
Please clean up the tables. product_categories
with product_id
and category_id
implies a many:many mapping between products and categories.
But the existence of category_id
in tmp_products
implies that a product belongs to only one category. This contradicts the many:many concept.
Which is it? Maybe tmp_products
needs main_category_id
? Or it is relation is not really many:many?
I also see parent_id
, which implies a hierarchy in tmp_products
. Is that correct? Is it relevant to this question?
As for 'proper indexing',...
This discusses optimal indexes for a many:many table (get rid of auto_inc; use composite PK, etc).- Do not index flags; such indexes won't be used due to poor cardinality.
- Learn to use "composite" indexes where appropriate.
- When using
MATCH
in theWHERE
clause of aSELECT
, theFULLTEXT
index will be the only index used.
Assuming
ON pc.product_id = p.id
AND pc.category_id = 395
AND p.parent_id = 0
AND p.sale_price BETWEEN 20 AND 120
then have these composite indexes:
p: PRIMARY KEY(id) -- (already exists)
p: INDEX(parent_id, sale_price)
pc: INDEX(category_id, product_id) -- (as mentioned above)
This set of indexes will happen to work whether or not you include the sale_price
limitation. Caveat: If you have other filtering, other indexes may be needed.
answered Aug 17 '18 at 0:03
Rick JamesRick James
43.9k22361
43.9k22361
add a comment |
add a comment |
Thanks for contributing an answer to Database Administrators Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f213394%2fmysql-proper-columns-indexing%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown