Query takes too long to execute when i add where clause - mysql

I have an 4 tables join query, when i execute without "where" takes like 13 seconds with where takes like 8 minutes.
I have no idea what to do in my mind when u use where to filter improve query perfomance but i'm mistaken
SELECT distinct tb_ProdutoComercial.nm_prodcomerc as tx_nome,
tb_parceiro.id_prodcomerc_pr as id_produto
FROM tb_vendedor
left join tb_tokenidparc
on tb_vendedor.nu_cdVendedorS4E = tb_tokenidparc.nu_cdVendedor4E_tk
left join tb_parceiro
on tb_tokenidparc.nu_cdCorretoraS4E_tk = tb_parceiro.id_corretora_pr
left join tb_ProdutoComercial
on tb_ProdutoComercial.id_prodcomerc = tb_parceiro.id_prodcomerc_pr
where tb_ProdutoComercial.en_status = '1'
EXPLAIN With Where
EXPLAIN Without Where
I'm looking for something with the same perfomance without where

As you are joining the tables on left side but you also filter them too that is the reason it is taking much time.
Here actually 5 queries are running according to the query.

Does this run better?
SELECT distinct tb_ProdutoComercial.nm_prodcomerc as tx_nome
,tb_parceiro.id_prodcomerc_pr as id_produto
FROM tb_vendedor
left join tb_tokenidparc on tb_vendedor.nu_cdVendedorS4E = tb_tokenidparc.nu_cdVendedor4E_tk
left join tb_parceiro on tb_tokenidparc.nu_cdCorretoraS4E_tk = tb_parceiro.id_corretora_pr
left join (select * from tb_ProdutoComercial where en_status='1') tb_ProdutoComercial on tb_ProdutoComercial.id_prodcomerc = tb_parceiro.id_prodcomerc_pr

Related

SQL query optimization for speed

So I was working on the problem of optimizing the following query I have already optimized this to the fullest from my side can this be further optimized?
select distinct name ad_type
from dim_ad_type x where exists ( select 1
from sum_adserver_dimensions sum
left join dim_ad_tag_map on dim_ad_tag_map.id=sum.ad_tag_map_id and dim_ad_tag_map.client_id=sum.client_id
left join dim_site on dim_site.id = dim_ad_tag_map.site_id
left join dim_geo on dim_geo.id = sum.geo_id
left join dim_region on dim_region.id=dim_geo.region_id
left join dim_device_category on dim_device_category.id=sum.device_category_id
left join dim_ad_unit on dim_ad_unit.id=dim_ad_tag_map.ad_unit_id
left join dim_monetization_channel on dim_monetization_channel.id=dim_ad_tag_map.monetization_channel_id
left join dim_os on dim_os.id = sum.os_id
left join dim_ad_type on dim_ad_type.id = dim_ad_tag_map.ad_type_id
left join dim_integration_type on dim_integration_type.id = dim_ad_tag_map.integration_type_id
where sum.client_id = 50
and dim_ad_type.id=x.id
)
order by 1
Your query although joined ok, is an overall bloat. You are using the dim_ad_type table on the outside, just to make sure it exists on the inside as well. You have all those left-joins that have NO bearing on the final outcome, why are they even there. I would simplify by reversing the logic. By tracing your INNER query for the same dim_ad_type table, I find the following is the direct line. sum -> dim_ad_tag_map -> dim_ad_type. Just run that.
select distinct
dat.name Ad_Type
from
sum_adserver_dimensions sum
join dim_ad_tag_map tm
on sum.ad_tag_map_id = tm.id
and sum.client_id = tm.client_id
join dim_ad_type dat
on tm.ad_type_id = dat.id
where
sum.client_id = 50
order by
1
Your query was running ALL dim_ad_types, then finding all the sums just to find those that matched. Run it direct starting with the one client, then direct with JOINs.

Mysql Join performance MongoDB, Cassandra

I have a join query which takes a lot of time to process.
SELECT
COUNT(c.id)
FROM `customers` AS `c`
LEFT JOIN `setting` AS `ssh` ON `c`.`shop_id` = `ssh`.`id`
LEFT JOIN `customer_extra` AS `cx` ON `c`.`id` = `cx`.`customer_id`
LEFT JOIN `customers_address` AS `ca` ON `ca`.`id` = `cx`.`customer_default_address_id`
LEFT JOIN `lytcustomer_tier` AS `ct` ON `cx`.`lyt_customer_tier_id` = `ct`.`id`
WHERE (c.shop_id = '12121') AND ((DATE(cx.last_email_open_date) > '2019-11-08'));
This is primarily because the table 'customers' has 2 million records.
I could go over into indexing etc. But, the larger point is, this 2.5 million could become a billion records 1 day.
I'm looking for solutions which can enhance performance.
I've given thought to
a) horizontal scalability. -: distribute the mysql table into different sections and query the count independently.
b) using composite indexes.
c) My favourite one -: Just create a seperate collection in mongodb or redis which only houses the count(output of this query) Since, the count is just 1 number. this will not require a huge size aka better query performance (Only question is, how many such queries are there, because that will increase size of the new collection)
Try this and see if it improve performance:
SELECT
COUNT(c.id)
FROM `customers` AS `c`
INNER JOIN `customer_extra` AS `cx` ON `c`.`id` = `cx`.`customer_id`
LEFT JOIN `setting` AS `ssh` ON `c`.`shop_id` = `ssh`.`id`
LEFT JOIN `customers_address` AS `ca` ON `ca`.`id` = `cx`.`customer_default_address_id`
LEFT JOIN `lytcustomer_tier` AS `ct` ON `cx`.`lyt_customer_tier_id` = `ct`.`id`
WHERE (c.shop_id = '12121') AND ((DATE(cx.last_email_open_date) > '2019-11-08'));
As I mention in the comment, since the condition AND ((DATE(cx.last_email_open_date) > '2019-11-08'));, already made customers table to INNER JOIN with customer_extra table, you might just change it to INNER JOIN customer_extra AS cx ON c.id = cx.customer_id and follow it with other LEFT JOIN.
The INNER JOIN will at least get the initial result to only return any customer who have last_email_open_date value based on what has been specified.
Say COUNT(*), not COUNT(c.id)
Remove these; they slow down the query without adding anything that I can see:
LEFT JOIN `setting` AS `ssh` ON `c`.`shop_id` = `ssh`.`id`
LEFT JOIN `customers_address` AS `ca` ON `ca`.`id` = `cx`.`customer_default_address_id`
LEFT JOIN `lytcustomer_tier` AS `ct` ON `cx`.`lyt_customer_tier_id` = `ct`.`id`
DATE(...) makes that test not "sargable". This works for DATE or DATETIME; and this is much faster:
cx.last_email_open_date > '2019-11-08'
Consider whether that should be >= instead of >.
Need an index on shop_id. (Please provide SHOW CREATE TABLE.)
Don't use LEFT JOIN when JOIN would work equally well.
If customer_extra is columns that should have been in customer, now is the time to move them in. That would let you use this composite index for even more performance:
INDEX(shop_id, last_email_open_date) -- in this order
With those changes, a billion rows in MySQL will probably not be a problem. If it is, there are still more fixes I can suggest.

How to reduce the query execution time in mysql

How to reduce the query execution time in mysql where table having records greater than 154381 and inner query should be used
This is my Query :
SELECT txn_gallery.gallery_image
FROM txn_gallery
WHERE villa_id IN(SELECT villa_id
FROM txn_notifications
LEFT JOIN mst_villa on mst_villa.sk_villa_id=txn_notifications.villa_id
WHERE txn_notifications.member_id='235' and txn_notifications.tran_status='Approved')
Your query is functionally identical to:
SELECT g.gallery_image
FROM txn_gallery g
JOIN txn_notifications n
ON n.villa_id = g.villa_id
WHERE n.member_id = 235
and n.tran_status = 'Approved'
An index on some combination of (villa_id,member_id,tran_status) would be useful
Its better to use join instead of inner query
JOIN can be faster than an equivalent subquery because the server might be able to optimize it better
So subqueries can be slower than LEFT [OUTER] JOIN

mysql query optimization given a sorting order and id being passed as parameter

I am trying to optimize this query:
SELECT ob.id, obs.relation
FROM object_relation obs , object_table ob
WHERE obs.parent_id = 'ID_being_passed_as_parameter'
AND ob.id = obs.child_id
AND ob.deleted_object_flag=0
AND ob.id_prefix in ('prefix_variAble_passed')
ORDER BY (SELECT m.value FROM metadata_table
m WHERE ob.version_id=m.version_id AND m.name='SORTING_CONDITION' )
Is is possible to optimize it?
Any suggestions would be of great help
Your query sucks because it's executing the subquery in the order by for every row.
Most subqueries can be turned into joins. This is what you should do too, as well as use joins in your main query:
SELECT ob.id, obs.relation
FROM object_relation obs
join object_table ob
on ob.id = obs.child_id
AND ob.deleted_object_flag=0
AND ob.id_prefix in ('prefix_variable_passed')
left join metadata_table m
on ob.version_id = m.version_id
AND m.name = 'SORTING_CONDITION'
WHERE obs.parent_id = 'ID_being_passed_as_parameter'
ORDER BY m.value;
This use of left join allows for there to be no matching row in metadata_table but still appear in the results.
Note also moving the predicates into the on clause of the join where they can be applied as the row is joined rather than at the end, which is much more efficient as the temporary result set is as small as possible.

MySql Query takes forever

hi I am doing A query to get some product info, but there is something strange going on, the first query returns resultset fast (.1272s) but the second (note that I just added 1 column) takes forever to complete (28-35s), anyone know what is happening?
query 1
SELECT
p.partnumberp,
p.model,
p.descriptionsmall,
p.brandname,
sum(remainderint) stockint
from
inventario_dbo.inventoryindetails ind
left join purchaseorders.product p on (p.partnumberp = ind.partnumberp)
left join inventario_dbo.inventoryin ins on (ins.inventoryinid= ind.inventoryinid)
group by partnumberp, projectid
query 2
SELECT
p.partnumberp,
p.model,
p.descriptionsmall,
p.brandname,
p.descriptiondetail,
sum(remainderint) stockint
from
inventario_dbo.inventoryindetails inda
left join purchaseorders.product p on (p.partnumberp = inda.partnumberp)
left join inventario_dbo.inventoryin ins on (ins.inventoryinid= inda.inventoryinid)
group by partnumberp, projectid
You shouldn't group by some columns and then select other columns unless you use aggregate functions. Only p.partnumberp and sum(remainderint) make sense here. You're doing a huge join and select and then the results for most rows just end up getting discarded.
You can make the query much faster by doing an inner select first and then joining that to the remaining tables to get your final result for the last few columns.
The inner select should look something like this:
select p.partnumberp, projectid, sum(remainderint) stockint
from inventario_dbo.inventoryindetails ind
left join purchaseorders.product p on (p.partnumberp = ind.partnumberp)
left join inventario_dbo.inventoryin ins on (ins.inventoryinid = ind.inventoryinid)
group by partnumberp, projectid
After the join:
select T1.partnumberp, T1.projectid, p2.model, p2.descriptionsmall, p2.brandname, T1.stockint
from
(select p.partnumberp, projectid, sum(remainderint) stockint
from inventario_dbo.inventoryindetails ind
left join purchaseorders.product p on (p.partnumberp = ind.partnumberp)
left join inventario_dbo.inventoryin ins on (ins.inventoryinid = ind.inventoryinid)
group by partnumberp, projectid) T1
left join purchaseorders.product p2 on (p2.partnumberp = T1.partnumberp)
Is descriptiondetail a really large column? Sounds like it could be a lot of text compared to the other fields based on its name, so maybe it just takes a lot more time to read from disk, but if you could post the schema detail for the purchaseorders.product table or maybe the average length of that column that would help.
Otherswise I would try running the query a few times and see you consistently get the same time results. Could just be load on the database server the time you got the slower result.