Why records arrive after 40 seconds - mysql

ayetler Table = 6500 rows
fihristayet Table = 13279 rows
Sql query :
SELECT ayetler.ayet_tr
FROM fihristayet,ayetler
WHERE (fihristayet.fihristAyet_ayet=ayetler.ayet_no AND
fihristayet.fihristAyet_sure_id=ayetler.sure_id)
AND fihristayet.fihristAyet_fihrist_id=354
I have 15 rows return. Why records arrive after 40 seconds

First, learn to use proper, explicit, standard JOIN syntax. Never use commas in the FROM clause. So, your query should look like this:
SELECT a.ayet_tr
FROM fihristayet f JOIN
ayetler a
ON f.fihristAyet_ayet = a.ayet_no AND
f.fihristAyet_sure_id = a.sure_id
WHERE f.fihristAyet_fihrist_id = 354;
Then you want indexes on fihristayet(fihristAyet_fihrist_id, fihristAyet_ayet, fihristAyet_sure_id) and ayetler(ayet_no, sure_id).

Related

Mysql filter by multiply ids

I can't finish writing query to filter row by multiply ids. Here is query:
select distinct `storage_file`.*, `storage_tag`.`id` as `tid` from `storage_file`
inner join `storage_file_tag` on `storage_file`.`id` = `storage_file_tag`.`storage_file_id`
inner join `storage_tag` on `storage_tag`.`id` = `storage_file_tag`.`storage_tag_id`
where `storage_file`.`user_id` = 17 and `storage_file`.`deleted_at` is null and
`storage_tag`.`id` IN(13,17);
So the result is without group by statement is:
So.. I need result only with two records which contain tid 13 and 17
And when i replace "IN(13,17)" with storage_tag.id = 13 AND storage_tag.id = 17 - i get no records at all
How can i write subquery which will work like a + b but not a OR b ?
I'm not sure what you do exactly but it seams, that the distinct is not working as you expect, because you select "*" from storage_file, as there are different values in the columns of storage_file, the result is distincted but over all selected columnns and so more the two are selected.
You can replace
... AND id IN (11,22)
with
... AND ( id = 11 OR id = 12)
You need the parentheses because WHERE operator precedence rules are very simple.
Of course,
... AND id = 11 AND id = 12
never returns anything because the id cannot have two different values at the same time.

MySQL in clause slow with 10 or more items

This query takes 18 seconds
SELECT `wd`.`week` AS `start_week`, `wd`.`hold_code`, COUNT(wd.hold_code) AS hold_code_count
FROM `weekly_data` AS `wd`
JOIN aol_reporting_hold_codes hc ON hc.hold_code = wd.hold_code AND chart = 'GR'
WHERE `wd`.`days` <= 6
AND `wd`.`hold_code` IS NOT NULL
AND NOT `wd`.`hold_code` = ''
AND `wd`.`week` >= '201717'
AND `wd`.`itemgroup` IN ('BOTDTO', 'BOTDWG', 'C&FORG', 'C&FOTO', 'MF-SUB', 'MI-SUB', 'PROPRI', 'PROPTO', 'STRSTO', 'STRSUB')
AND `production_type` = 2
AND `contract` = "1234"
AND `project` = 8
GROUP BY `start_week`, `wd`.`hold_code`
This query takes 4 seconds
SELECT `wd`.`week` AS `start_week`, `wd`.`hold_code`, COUNT(wd.hold_code) AS hold_code_count
FROM `weekly_data` AS `wd`
JOIN aol_reporting_hold_codes hc ON hc.hold_code = wd.hold_code AND chart = 'GR'
WHERE `wd`.`days` <= 6
AND `wd`.`hold_code` IS NOT NULL
AND NOT `wd`.`hold_code` = ''
AND `wd`.`week` >= '201717'
AND `wd`.`itemgroup` IN ('BOTDWG', 'C&FORG', 'C&FOTO', 'MF-SUB', 'MI-SUB', 'PROPRI', 'PROPTO', 'STRSTO', 'STRSUB')
AND `production_type` = 2
AND `contract` = "1234"
AND `project` = 8
GROUP BY `start_week`, `wd`.`hold_code`
All I have done is removed one item from the IN clause. I can remove any one of the items. It runs in 4 seconds as long as there are 9 items or less. It takes 18 seconds to run as soon as I increase to 10 items.
I thought MySQL limited length of command by size i.e. 1MB
More than just the EXPLAIN, use EXPLAIN FORMAT=JSON and get the "Optimizer trace" for the query. I suspect the length of the IN leads to picking a different query plan.
There is virtually no limit to the number of items in IN. I have seen as many as 70K.
That aside, you may be able to speed up even the 4-sec version...
I suggest having this index. Grrr... I can't tell which columns are in which tables. So, if these are all in one table, then make such an index:
INDEX(production_type, contract, project) -- in any order
If those are all in wd, then tack on a 4th column - any of week, itemgroup, days.
Be cautious about COUNT(wd.hold_code).
COUNT(x) checks x for being non-NULL; is that what you want? If not, then simply say COUNT(*).
When JOINing, then GROUP BY, you get an "explode-implode". The number of intermediate rows is big; that is when the COUNT is performed.
It seems wrong to both COUNT(hold_code) and GROUP BY hold_code. What are you trying to do?
For further discussion, please provide SHOW CREATE TABLE and EXPLAIN.
Please note MySql IN clause limit is established with max_allowed_packet value. You may check with NOT IN if results are faster. Also I suggest put values to be checked with IN clause under a buffer string instead of comma separated values and then give a try.

Optimize query mysql search

I have the following SQL but its execution this very slow, takes about 45 seconds, the table has 15 million record, how can I improve?
SELECT A.*, B.ESPECIE
FROM
(
SELECT
A.CODIGO_DOCUMENTO,
A.DOC_SERIE,A.DATA_EMISSAO,
A.DOC_NUMERO,
A.CF_NOME,
A.CF_SRF,
A.TOTAL_DOCUMENTO,
A.DOC_MODELO
FROM MOVIMENTO A
WHERE
A.CODIGO_EMPRESA = 1
AND A.CODIGO_FILIAL = 5
AND A.DOC_TIPO_MOVIMENTO = 1
AND A.DOC_MODELO IN ('65','55')
AND (A.CF_NOME LIKE '%TEXT_SEARCH%'
OR A.CF_CODIGO LIKE 'TEXT_SEARCH%'
OR A.CF_SRF LIKE 'TEXT_SEARCH%'
OR A.DOC_SERIE LIKE 'TEXT_SEARCH%'
OR A.DOC_NUMERO LIKE 'TEXT_SEARCH%')
ORDER BY A.DATA_EMISSAO DESC , A.CODIGO_DOCUMENTO DESC
LIMIT 0, 100
) A
LEFT JOIN MODELODOCUMENTOFISCAL B ON A.DOC_MODELO = B.CODMODELO
For this query, I would start with an index on MOVIMENTO(CODIGO_EMPRESA, CODIGO_FILIAL, DOC_MODELO) and MODELODOCUMENTOFISCAL(CODMODELO).
That should speed the query.
If it doesn't you may need to consider a full text search to handle the LIKE clauses. I do note that you only have a wildcard at the beginning of one of the patterns. Is that intentional?

SQL Statement running extreamly Slow

Okay I have look through several posts about SQL running slow and I didn't see anything similar to this, so my apologies if I missed one. I was asked about a month ago to create a view that would allow the user to report what hasn't been billed yet, and the SQL is joining 4 tables together. One is 1.2 million records ish. the rest are between 80K - 250K. (Please note that this should only return around 100 records after the where statements).
SELECT C.Cltnum + '.' + C.CltEng AS [ClientNum],
C.CPPLname,
w.WSCDesc,
MIN(w.Wdate) AS [FirstTDate],
w.WCodeCat,
w.WCodeSub,
SUM(w.Wbilled) AS [Billed],
SUM(w.Whours * w.Wrate) AS [Billable Wip],
sum(ar.[ARProgress]) AS [Progress],
w.Winvnum,
-- dbo.GetInvoiceAmount(w.Winvnum) AS [InvoiceAmount],
SUM(cb.cinvar) AS [AR Balance]
FROM dbo.WIP AS w
--Never join on a select statement
--join BillingAuditCatagoriesT bac on w.WCodeCat = bac.Catagory and w.WCodeSub = bac.Subcatagory
INNER JOIN dbo.Clients AS C ON w.WCltID = C.ID
JOIN dbo.ClientBuckets AS cb on c.cltnum = cb.cltnum
JOIN dbo.AcctsRec AS ar on ar.arapplyto = w.[Winvnum]
-- WHERE w.wcodecat = '1AUDT'
GROUP BY C.Cltnum, C.CltEng, C.CPPLname, w.WCodeCat, w.Wdate, w.Winvnum, w.WCodeSub, w.WSCDesc
so, where I think there may be a problem is that Category is a varchar it is xat, ACT, BID and there are about 15 different Category. this is the same as SubCat. you will notice that there are 3 functions on this and they are GetJamesProgress Which is = (SELECT sum(Amount) From Progress Where inv = w.invnum) and the same with GetInvoiceAmount and GetJamesARBalance. I know that this is bad to do but when I join by invoice number it takes even longer than with out them.
Please help thanks so much!

MySQL - get all column averages also with a 'total' average

I have a MySQL table which looks like this:
id load_transit load_standby
1 40 20
2 30 15
3 50 10
I need to do the following calculations:
load_transit_mean = (40+30+50)/3 = 40
load_standby_mean = (20+15+10)/3 = 15
total_mean = (40+15)/2 = 27.5
Is it possible to do this in a single query? What would the best design be?
I need my answer to be scalable (the real design has more rows and columns), and able to handle some rows containing NULL.
I believe this would do it:
SELECT AVG(Load_transit)
, AVG(load_standby)
, (AVG(Load_transit) + AVG(load_standby))/2.0
FROM table
The AVG() function handles NULL's in that it ignores them, if you want the NULL row to be counted in your denominator you can replace AVG() with SUM() over COUNT(*), ie:
SUM(load_transit)/COUNT(*)
Regarding scalability, manually listing them out like above is probably the simplest solution.