The following query is timing out after 600 seconds.
update placed p
,Results r
set p.position = r.position
where p.competitor = r.competitor
AND p.date = r.date
AND REPLACE(p.time,":","") = r.time;
The structure is as follows:
'CREATE TABLE `placed` (
`idplaced` varchar(50) DEFAULT NULL,
`date` decimal(8,0) DEFAULT NULL,
`time` varchar(45) DEFAULT NULL,
`field1` varchar(45) DEFAULT NULL,
`competitor` varchar(45) DEFAULT NULL,
`field2` int(2) DEFAULT NULL,
`field3` varchar(45) DEFAULT NULL,
`field4` varchar(45) DEFAULT NULL,
`field5` decimal(6,2) DEFAULT NULL,
`field6` decimal(10,2) DEFAULT NULL,
`field7` decimal(6,2) DEFAULT NULL,
`field8` char(1) DEFAULT NULL,
`field9` varchar(45) DEFAULT NULL,
`position` char(4) DEFAULT NULL,
`field10` decimal(6,2) DEFAULT NULL,
`field11` char(1) DEFAULT NULL,
`field12` char(1) DEFAULT NULL,
`field13` decimal(6,2) DEFAULT NULL,
`field14` decimal(6,2) DEFAULT NULL,
`field15` decimal(6,2) DEFAULT NULL,
`field16` decimal(6,2) DEFAULT NULL,
`field17` decimal(6,2) DEFAULT NULL,
`field18` char(1) DEFAULT NULL,
`field19` char(20) DEFAULT NULL,
`field20` char(1) DEFAULT NULL,
`field21` char(5) DEFAULT NULL,
`field22` char(5) DEFAULT NULL,
`field23` int(11) DEFAULT NULL
PRIMARY KEY (`idplaced`),
UNIQUE KEY `date_time_competitor_field18_combo` (`date`,`time`,`competitor`,`field18`)
) ENGINE=InnoDB AUTO_INCREMENT=100688607 DEFAULT CHARSET=latin1;
CREATE TABLE `results` (
`idresults` int(11) NOT NULL AUTO_INCREMENT,
`date` char(8) DEFAULT NULL,
`time` char(4) DEFAULT NULL,
`field1` varchar(45) DEFAULT NULL,
`competitor` varchar(45) DEFAULT NULL,
`position` char(4) DEFAULT NULL,
`field2` varchar(45) DEFAULT NULL,
`field3` decimal(2,0) DEFAULT NULL,
PRIMARY KEY (`idresults`)
) ENGINE=InnoDB AUTO_INCREMENT=6644 DEFAULT CHARSET=latin1;
The PLACED table has 65,000 records, the RESULTS table has 9,000 records.
I am assuming the solution involves a JOIN statement of some descript, and I have tried taking several suggestions from this site, but am simply not finding the answer I am looking for. Simply put, I would be grateful for suggestions on this. I can put up example tables / create table code if requried.
The index cannot be used efficiently to perform the join because of your REPLACE operation.
I'd suggest creating an index with the columns in the following slightly different order:
(date, competitor, time, position)
It may also help to add this index on both tables.
It would be even better if you could modify the data in the database so that the data in the time column was stored in the same format in both tables.
First of all, you'd better send us your full tables description, using
show create table
Second, you'd better use join syntax :
update placed p
join Results r on r.competitor = p.competitor
set p.position = r.position
where p.date = r.date
AND REPLACE(p.time,":","") = r.time;
Hope this will help.
Related
I have a few problems with MYSQL database that I can't solve.
My query below is taking too much time and making the system hang. I'm trying to use the "JOIN" construct to develop this. But this time my aggregation, which I'm trying to do with "SUM", reduces the query to one line. Is it ok to do this job with "JOIN"? or how should i improve this query.
This database works with a total of 22 client devices in ASP .NET application. As I mentioned above, in cases where the query time is long, when the client devices send a query to the database at the same time, the client device freezes. What I don't understand is why a query in the browser app is making all devices wait. Isn't each query processed as a separate "Thread" in MYSQL? So if a query has a return time of 10 seconds, will all clients wait 10 seconds for the query to be answered in the browser?
SELECT *,
(SELECT MachModel FROM machine WHERE MachCode=workorder.MachCode) AS MachModel,
(SELECT RawMaterialDescription FROM rawmaterials WHERE RawMaterialCode=workorder.ProductRawMaterial) AS RawMaterialDescr,
(SELECT RawMaterialColor FROM rawmaterials WHERE RawMaterialCode=workorder.ProductRawMaterial) AS RawMaterialColor,
(SELECT StaffName FROM staff WHERE AccountName=workorder.AssignStaff) AS AssignStaffName,
(SELECT StaffCode FROM staff WHERE AccountName=workorder.AssignStaff) AS AssignStaffCode,
(SELECT MachStatus FROM machine WHERE MachCode=workorder.MachCode) AS MachStatus,
(SELECT SUM(xStopTime) FROM workorderb WHERE xWoNumber=workorder.WoNumber) AS WoTotalStopTime
FROM workorder
WHERE WoStatus=3
ORDER BY PlanProdStartDate DESC, WoSortNumber, WoNumber LIMIT 100
SELECT workorder.*,machine.MachModel,machine.MachStatus,rawmaterials.RawMaterialDescription,rawmaterials.RawMaterialColor,staff.StaffName,staff.StaffCode,SUM(workorderb.xStopTime)
FROM workorder
LEFT JOIN machine ON machine.MachCode=workorder.MachCode
LEFT JOIN rawmaterials ON rawmaterials.RawMaterialCode=workorder.ProductRawMaterial
LEFT JOIN staff ON staff.AccountName=workorder.AssignStaff
LEFT JOIN workorderb ON workorderb.xWoNumber=workorder.WoNumber
WHERE workorder.WoStatus=3
ORDER BY workorder.PlanProdStartDate DESC, workorder.WoSortNumber, workorder.WoNumber LIMIT 100
CREATE TABLE `workorder` (
`WoNumber` varchar(20) NOT NULL,
`MachCode` varchar(15) NOT NULL,
`PlannedMoldCode` varchar(10) NOT NULL,
`PartyNumber` smallint(6) NOT NULL,
`PlanProdCycleTime` smallint(6) NOT NULL,
`CalAverageCycleTime` float(15,1) unsigned NOT NULL,
`ProductRawMaterial` varchar(30) NOT NULL,
`PlanProdStartDate` date NOT NULL,
`PlanProdFinishDate` int(10) unsigned NOT NULL,
`WoStartDate` datetime DEFAULT NULL,
`WoFinishDate` datetime DEFAULT NULL,
`WoWorkTime` int(10) unsigned NOT NULL,
`WoSystemProductivity` smallint(6) unsigned NOT NULL,
`AssignStaff` varchar(50) DEFAULT '',
`WoStatus` smallint(6) NOT NULL,
`WoSortNumber` int(10) unsigned NOT NULL,
`CycleCount` int(11) unsigned NOT NULL,
`ControlDate` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
`WoProductionStatus` smallint(6) NOT NULL DEFAULT '0',
`Creator` varchar(50) NOT NULL,
`Changer` varchar(50) NOT NULL,
`CreateDate` datetime NOT NULL,
PRIMARY KEY (`WoNumber`) USING BTREE,
KEY `WoNumber` (`WoNumber`) USING BTREE,
KEY `WoNumber_2` (`WoNumber`) USING BTREE,
KEY `WoNumber_3` (`WoNumber`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
CREATE TABLE `machine` (
`MachCode` varchar(15) NOT NULL,
`MachModel` varchar(30) NOT NULL,
`FirstProdDate` date NOT NULL,
`MachCapacity` smallint(6) NOT NULL,
`MachStatus` smallint(6) NOT NULL,
`NowMoldOnMach` varchar(10) NOT NULL DEFAULT '',
`NowMachOperator` varchar(50) NOT NULL DEFAULT '',
`NowWorkOrder` varchar(20) NOT NULL DEFAULT '',
`IPNumber` varchar(15) NOT NULL,
`Creator` varchar(50) NOT NULL,
`Changer` varchar(50) NOT NULL,
`ControlDate` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`OperatorLoginDate` datetime DEFAULT NULL,
`Message` varchar(500) DEFAULT NULL,
`MessageReaded` smallint(6) DEFAULT '0',
`StaffName` varchar(50) DEFAULT 'OSIS',
`StaffImage` varchar(255) DEFAULT '',
`StopDesc` varchar(30) DEFAULT 'OSIS',
`StopTime` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`MachCode`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
CREATE TABLE `rawmaterials` (
`RawMaterialCode` varchar(15) NOT NULL,
`RawMaterialDescription` varchar(30) NOT NULL,
`RawMaterialColor` varchar(30) NOT NULL,
PRIMARY KEY (`RawMaterialCode`) USING BTREE,
KEY `RawMaterialCode` (`RawMaterialCode`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
CREATE TABLE `staff` (
`StaffCode` varchar(15) DEFAULT NULL,
`StaffCardCode` varchar(10) DEFAULT NULL,
`StaffName` varchar(50) NOT NULL,
`StaffPassword` varchar(10) NOT NULL,
`StaffStatus` smallint(6) NOT NULL DEFAULT '2',
`StaffDateOfStart` date NOT NULL,
`StaffBirthDay` date DEFAULT NULL,
`StaffGender` varchar(5) DEFAULT NULL,
`StaffRoleA` smallint(6) NOT NULL,
`StaffEmail` varchar(100) NOT NULL,
`StaffImageLink` varchar(255) DEFAULT NULL,
`AccountName` varchar(50) NOT NULL,
`StaffRoleB` smallint(6) NOT NULL,
`StaffRoleD` smallint(6) NOT NULL,
`StaffRoleE` smallint(6) NOT NULL,
`StaffRoleC` smallint(6) NOT NULL,
`StaffRoleF` smallint(6) NOT NULL,
`StaffRoleG` smallint(6) NOT NULL,
`StaffRoleH` smallint(6) NOT NULL,
`StaffRoleI` smallint(6) NOT NULL,
`StaffRoleJ` smallint(6) NOT NULL,
`StaffRoleK` smallint(6) NOT NULL,
`StaffRoleL` smallint(6) NOT NULL,
`StaffRoleM` smallint(6) NOT NULL,
`StaffRoleN` smallint(6) NOT NULL,
`StaffConnection` smallint(6) NOT NULL DEFAULT '2',
`MachineWorked` varchar(15) DEFAULT NULL,
`WorkOrderWorked` varchar(20) DEFAULT NULL,
`StaffGroup` varchar(50) NOT NULL,
`Creator` varchar(50) NOT NULL,
`Changer` varchar(50) DEFAULT NULL,
PRIMARY KEY (`AccountName`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
CREATE TABLE `workorderb` (
`xWoNumber` varchar(20) NOT NULL,
`xMachCode` varchar(15) NOT NULL,
`xPlannedMoldCode` varchar(10) NOT NULL,
`xPartyNumber` smallint(6) NOT NULL,
`xStaffName` varchar(50) NOT NULL,
`xStopCode` smallint(6) NOT NULL,
`xStopStartTime` datetime NOT NULL,
`xStopFinishTime` datetime DEFAULT NULL,
`xStopTime` int(11) DEFAULT NULL,
PRIMARY KEY (`xMachCode`,`xStopStartTime`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC
Your query with the joins was nearly there: it was just missing a GROUP BYclause.
I have replaced workorder.* with workorder.WoNumber in the SELECT and added GROUP BY workorder.WoNumber.
You can add as many columns from workorder in the SELECT as you like but you must list them in the GROUP BY.
SELECT workorder.WoNumber,machine.MachModel,machine.MachStatus,rawmaterials.RawMaterialDescription,rawmaterials.RawMaterialColor,staff.StaffName,staff.StaffCode,SUM(workorderb.xStopTime)
FROM workorder
LEFT JOIN machine ON machine.MachCode=workorder.MachCode
LEFT JOIN rawmaterials ON rawmaterials.RawMaterialCode=workorder.ProductRawMaterial
LEFT JOIN staff ON staff.AccountName=workorder.AssignStaff
LEFT JOIN workorderb ON workorderb.xWoNumber=workorder.WoNumber
WHERE workorder.WoStatus=3
GROUP BY workorder.WoNumber \* <<= ADD OTHER COLUMNS HERE AS NEEDED *\
ORDER BY workorder.PlanProdStartDate DESC, workorder.WoSortNumber, workorder.WoNumber LIMIT 100;
db<>fiddle here
Use InnoDB, not MyISAM. MyISAM locks the entire table when INSERTing; InnoDB can often allow other threads to run when inserting.
Other notes
workorder has 4 identical indexes on wonumber; keep the PK, toss the rest. Note that a PRIMARY KEY is an index. Check the other tables for redundant Keys.
Do you need the mixture of DESC and ASC in ORDER BY PlanProdStartDate DESC, WoSortNumber, WoNumber? If not, there may be an optimization here.
As Kendle suggests, JOINs would be faster since there are cases where the same table is needed twice. If values might be missing, then LEFT might be useful; it won't change the performance.
Needed:
workorderb: INDEX(xWoNumber, xStopTime)
Is xStopTime an elapsed time? Or a time of day?
query is simple, as below:
select count(1) from ec_account a join ec_card b on a.id = b.AccountId
there are 2.5 million rows in either ec_account and ec_card.(InnoDB)
here is the execution plan:
execution plan
as you see,
it already added index and used it, but the query still costed almost 60 seconds, is there any way could optimize it except changing database(mariadb has no such choke point as far as i know).
here is table DDL,ec_ccount:
CREATE TABLE `ec_account` (
`Id` varchar(64) NOT NULL,
`AccountType` varchar(32) NOT NULL,
`Name` varchar(32) NOT NULL,
`Status` tinyint(3) unsigned NOT NULL,
`IDCardType` varchar(32) DEFAULT NULL,
`IDCardNo` varchar(64) DEFAULT NULL,
`Password` varchar(256) DEFAULT NULL,
`PasswordHalt` varchar(128) DEFAULT NULL,
`Sex` varchar(8) DEFAULT NULL,
`BirthDay` datetime NOT NULL,
`Mobile` varchar(16) DEFAULT NULL,
`Address` varchar(64) DEFAULT NULL,
`Linkman` varchar(32) DEFAULT NULL,
`LinkmanRelation` varchar(16) DEFAULT NULL,
`LinkmanTel` varchar(16) DEFAULT NULL,
`Remark` varchar(128) DEFAULT NULL,
`Nationality` varchar(32) DEFAULT NULL,
`Nation` varchar(32) DEFAULT NULL,
`MaritalStatus` varchar(8) DEFAULT NULL,
`NativePlace` varchar(64) DEFAULT NULL,
`Occupation` varchar(32) DEFAULT NULL,
`BloodType` varchar(8) DEFAULT NULL,
`Education` varchar(8) DEFAULT NULL,
`LinkmanAddress` varchar(64) DEFAULT NULL,
`HomeAddress` varchar(128) DEFAULT NULL,
`Email` varchar(64) DEFAULT NULL,
`CompanyName` varchar(64) DEFAULT NULL,
`CompanyAddress` varchar(128) DEFAULT NULL,
`CompanyTel` varchar(16) DEFAULT NULL,
`Creator` char(36) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`CreateTime` datetime NOT NULL,
`LastModifier` char(36) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`LastModifyTime` datetime DEFAULT NULL,
`Avatar` longblob,
PRIMARY KEY (`Id`),
KEY `IX_Name` (`Name`) USING HASH,
KEY `Idx_IDCard_Account` (`IDCardType`,`IDCardNo`) USING HASH,
KEY `Idx_Mobile` (`Mobile`) USING HASH,
KEY `Idx_CreateTime` (`CreateTime`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
and ec_card :
CREATE TABLE `ec_card` (
`Id` char(36) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`AccountId` varchar(64) NOT NULL,
`CardType` varchar(32) NOT NULL,
`CardNo` varchar(32) NOT NULL,
`Status` tinyint(3) unsigned NOT NULL,
`IsPasswordAuth` tinyint(1) NOT NULL,
PRIMARY KEY (`Id`),
UNIQUE KEY `Idx_Unique_AccountId_CardType` (`AccountId`,`CardType`) USING HASH,
UNIQUE KEY `Idx_Unique_CardType_CardNo` (`CardType`,`CardNo`) USING HASH,
KEY `Idx_Uniques_AccountId` (`AccountId`) USING BTREE,
CONSTRAINT `FK_ec_card_ec_account_AccountId` FOREIGN KEY (`AccountId`) REFERENCES `ec_account` (`Id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Not without fundamentally changing the query.
There are no conditions on your query! It selects all 2.5 million rows from ec_card, as well as every matching row from ec_account. Reading all this data from disk and sending it over the network is the bottleneck; there is no way to change that without changing what the query does.
Here is a workaround for you. I think it would run much faster, and get the same result.
Calculate the total count of ec_account:
SELECT count(1) AS total_count FROM ec_account;
Calculate the amount of records those existed in ec_account but not existed in ec_card:
SELECT count(1) AS missing_count
FROM ec_account a LEFT JOIN ec_card b on a.id = b.AccountId
WHERE b.AccountId IS NULL;
Matched count = total_count - missing_count
The core problem here is that you combined two large table together, it requires a lot of memory and it apparently needs a lot of time to finish.
try it using correlated subquery. This might help:
select count(1) from ec_account a where exists (select * from ec_card b
where b.AccountId=a.id)
Also, other than indexing following strategies generally help:
- Denormalization
- Caching results
- Using a NoSQL database
so I got a mysql database with 2 tables, one (sd_clients) with about 24k entries:
CREATE TABLE `sd_clients` (
`ms_id` varchar(10) NOT NULL,
`ms_share_id` varchar(10) NOT NULL,
`short_name` varchar(25) DEFAULT NULL,
`standard_name` varchar(75) DEFAULT NULL,
`legal_name` varchar(150) DEFAULT NULL,
`country` varchar(4) DEFAULT NULL,
`status` tinyint(1) DEFAULT NULL COMMENT '1=Paid Client | 2=Non-Paid Client',
`user_id` int(11) DEFAULT NULL,
`summary` text,
`sector` int(4) DEFAULT NULL,
`sub_sector` int(4) DEFAULT NULL,
`business_country` char(3) DEFAULT NULL,
`created_at` date DEFAULT NULL,
`is_paid` int(1) NOT NULL DEFAULT '0' COMMENT '0 = Non-Paid Client | 1=Paid Client',
`description_en` text,
`description_zh-hans` text,
`description_zh-hant` text,
`highlights_en` text,
`highlights_zh-hans` text,
`highlights_zh-hant` text,
`logo` varchar(255) DEFAULT NULL,
`summary_subsection_title_en` varchar(500) DEFAULT NULL,
`summary_subsection_title_zh-hans` varchar(500) DEFAULT NULL,
`summary_subsection_title_zh-hant` varchar(500) DEFAULT NULL,
`summary_subsection_text_en` text,
`summary_subsection_text_zh-hans` text,
`summary_subsection_text_zh-hant` text,
`summary_short_en` varchar(2000) DEFAULT NULL,
`summary_short_zh-hans` varchar(2000) DEFAULT NULL,
`summary_short_zh-hant` varchar(2000) DEFAULT NULL,
`other_information_en` text,
`other_information_zh-hans` text,
`other_information_zh-hant` text,
`change_percentage` decimal(10,3) DEFAULT NULL,
`id_sector` bigint(3) DEFAULT NULL,
`id_subsector` bigint(3) DEFAULT NULL,
`background_info_en` text,
`background_info_zh-hans` text,
`background_info_zh-hant` text,
`share_id_displayed` varchar(10) DEFAULT NULL,
PRIMARY KEY (`ms_id`) KEY_BLOCK_SIZE=1024,
UNIQUE KEY `ms_id` (`ms_id`) KEY_BLOCK_SIZE=1024,
KEY `share_id_displayed` (`share_id_displayed`) KEY_BLOCK_SIZE=1024
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
SET FOREIGN_KEY_CHECKS=1;
And another called sd_clients_daily_stocks, with about 50 million entries:
CREATE TABLE `sd_clients_daily_stocks` (
`ms_id` varchar(10) NOT NULL,
`ms_share_id` varchar(10) DEFAULT NULL,
`created_at` date DEFAULT NULL,
`symbol` varchar(32) DEFAULT NULL,
`exchange_id` char(5) DEFAULT NULL,
`volume` bigint(18) DEFAULT NULL,
`day_low` decimal(19,6) DEFAULT NULL,
`day_high` decimal(19,6) DEFAULT NULL,
`market_cap` bigint(18) DEFAULT NULL,
`open_price` decimal(19,6) DEFAULT NULL,
`close_price` decimal(19,6) DEFAULT NULL,
`enterprise_value` bigint(18) DEFAULT NULL,
`currency_id` char(3) DEFAULT NULL,
`valoren` varchar(20) DEFAULT NULL,
`cusip` char(9) DEFAULT NULL,
`isin` varchar(12) DEFAULT NULL,
`sedol` varchar(7) DEFAULT NULL,
`ipo_date` date DEFAULT NULL,
`is_depositary_receipt` tinyint(1) DEFAULT NULL,
`depositary_receipt_ratio` decimal(9,4) DEFAULT NULL,
`security_type` char(10) DEFAULT NULL,
`share_class_description` varchar(1000) DEFAULT NULL,
`share_class_status` char(1) DEFAULT NULL,
`is_primary_share` tinyint(1) DEFAULT NULL,
`is_dividend_reinvest` tinyint(1) DEFAULT NULL,
`is_direct_invest` tinyint(1) DEFAULT NULL,
`investment_id` char(10) DEFAULT NULL,
`ipo_offer_price` decimal(19,6) DEFAULT NULL,
`delisting_date` date DEFAULT NULL,
`delisting_reason` varchar(100) DEFAULT NULL,
`mic` char(10) DEFAULT NULL,
`common_share_sub_type` varchar(32) DEFAULT NULL,
`ipo_offer_price_range` varchar(32) DEFAULT NULL,
`exchange_sub_market_global_id` char(10) DEFAULT NULL,
`conversion_ratio` decimal(19,9) DEFAULT NULL,
KEY `ms_id` (`ms_id`) USING HASH,
KEY `ms_share_id` (`ms_share_id`) USING HASH,
KEY `symbol` (`symbol`),
KEY `exchange_id` (`exchange_id`),
KEY `created_at` (`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
SET FOREIGN_KEY_CHECKS=1;
I'm trying to run a fairly simple query:
SELECT DISTINCT
sd_clients.ms_id,
sd_clients.standard_name,
sd_clients.is_paid,
sd_clients.logo,
sd_clients.change_percentage,
(
SELECT
CONCAT(
`exchange_id`, '|--|',
`symbol`, '|--|',
`close_price`, '|--|',
`day_low`, '|--|',
`day_high`
) as items
FROM sd_clients_daily_stocks
WHERE ms_share_id = sd_clients.share_id_displayed
ORDER BY created_at DESC
LIMIT 1
) as company_data
FROM sd_clients
GROUP BY ms_id
ORDER BY sd_clients.standard_name ASC
LIMIT 10
But for some reason, it's taking way too long (like over 1 minute), to get any results, any idea why?
BTW, it works just fine if I remove the subquery, but I need it because the rest of the data, is in another table. Also, I know I could get the results without the subquery first, but I have other queries where the subquery must be there.
I also noticed that it gets blazing fast if I use a string instead of "sd_clients.share_id_displayed" on the subquery.
You should try an index on sd_clients_daily_stocks(ms_share_id, created_at).
You can add the additional columns from the select if you want a covering index.
You would probably be better off joining on a non-correlated subquery based off your current subquery; using this kind of technique here to find the most recent rows for each in the new subquery.
Edit: I was thinking more something like this:
SELECT DISTINCT sd_clients.ms_id, sd_clients.standard_name, sd_clients.is_paid, sd_clients.logo, sd_clients.change_percentage
, scdsB.items
FROM sd_clients
INNER JOIN (
SELECT scdsA.ms_share_id
, CONCAT(
scdsA.`exchange_id`, '|--|', scdsA.`symbol`, '|--|',
scdsA.`close_price`, '|--|', scdsA.`day_low`, '|--|', scdsA.`day_high`
) as items
FROM sd_clients_daily_stocks AS scdsA
INNER JOIN (
SELECT ms_share_id, MAX(created_at)
FROM sd_clients_daily_stocks
GROUP BY ms_share_id
) AS lasts
ON scdsA.ms_share_id = lasts.ms_share_id
AND scdsA.created_at = lasts.created_at
) scdsB
ON sd_clients.share_id_displayed = scdsB.ms_share_id
GROUP BY sd_clients.ms_id
ORDER BY sd_clients.standard_name ASC
LIMIT 10;
... But even this likely won't reduce the speed much more, if any, from the 12 seconds. At that point you are better off looking into indexes that could help. For example, the lasts grouping subquery that finds the most recent(max) created_at value for each ms_share_id value would benefit from an index on sd_clients_daily_stocks (ms_shared_id, created_at) as would the the JOIN it is used in.
I have the following simple join query
SELECT
count(*)
FROM
DBx.caseview p2015
INNER JOIN DBy.caseview p2014 ON p2015.casenumber=p2014.casenumber;
For some reason it just leaves MySQL hanging there for a lot of time until I get tired and cancel it. On the contrary, if run exactly the same code on MSSQL with the same data set the query takes a few seconds at most.
Is there a parameter that needs to be changed on MySQL to speed up this type of queries?
Here's my table in MySQL
CREATE TABLE `caseview` (
`ID` bigint(20) NOT NULL AUTO_INCREMENT,
`CASEID` varchar(18) DEFAULT NULL,
`CASENUMBER` int(10) DEFAULT NULL,
`ACCOUNTID` varchar(18) DEFAULT NULL,
`ACCOUNT` varchar(256) DEFAULT NULL,
`ASSETID` varchar(18) DEFAULT NULL,
`SAPPRODUCTGROUP` varchar(10) DEFAULT NULL,
`PRODUCT` varchar(128) DEFAULT NULL,
`FAMILY` varchar(128) DEFAULT NULL,
`CONTACTID` varchar(18) DEFAULT NULL,
`OWNERID` varchar(18) DEFAULT NULL,
`TYPE` varchar(128) DEFAULT NULL,
`PRIORITY` varchar(24) DEFAULT NULL,
`ORIGIN` varchar(24) DEFAULT NULL,
`SUBJECT` varchar(256) DEFAULT NULL,
`STATUS` varchar(24) DEFAULT NULL,
`LASTACTIVITY` varchar(1024) DEFAULT NULL,
`INITALDESCRIPTION` varchar(1024) DEFAULT NULL,
`CLOSEDDATE` datetime DEFAULT NULL,
`CREATEDDATE` datetime DEFAULT NULL,
`LASTMODIFIEDDATE` datetime DEFAULT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `ID_UNIQUE` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=122393 DEFAULT CHARSET=utf8;
There's two tables with exactly the same configuration as above, just different data
DBx.caseview p2015 has 197647 rows
DBy.caseview p2014 has 122392 rows
Create an Index for CASENUMBER field.
ALTER TABLE `caseview` ADD INDEX ( `CASENUMBER` ) ;
Give it a few seconds to create the index and run the query again.
I have three tables in MySQL:
CREATE TABLE `mlm`.`facturacion_2012_drm_base` ( `custid`
varchar(20) NOT NULL, `fecha` date NOT NULL, `docid` varchar(20)
NOT NULL, `billid` varchar(20) NOT NULL, `movimiento` varchar(20)
DEFAULT NULL, `movid` varchar(20) DEFAULT NULL, `medio_pago`
varchar(40) DEFAULT NULL, `digitos` varchar(20) DEFAULT NULL,
`monto_facturado` decimal(20,2) NOT NULL, `monto_pagado`
decimal(20,2) NOT NULL, `monto_usado` decimal(20,2) NOT NULL,
`documento` varchar(2) NOT NULL, `codigo_pago` varchar(5) DEFAULT
NULL, `desc_pago` varchar(100) DEFAULT NULL, `sociedad`
varchar(45) DEFAULT NULL, `sociedad_bonif` varchar(45) DEFAULT NULL,
KEY `billid` (`billid`), KEY `motors_no_fact`
(`custid`,`billid`,`fecha`,`documento`) USING BTREE, KEY
`facturacion` (`custid`,`fecha`,`documento`) USING BTREE )
ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;
CREATE TABLE `mlm`.`facturacion_2012_drm_cortes` ( `id` bigint(20)
NOT NULL AUTO_INCREMENT, `fecha_inicial` date NOT NULL,
`fecha_final` date NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM
AUTO_INCREMENT=433 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;
CREATE TABLE `mlm`.`facturacion_2012_drm_emitidas` ( `id`
bigint(20) NOT NULL AUTO_INCREMENT, `custid` varchar(20) NOT NULL,
`fecha_emision` date NOT NULL, `id_fechas` bigint(20) NOT NULL,
`monto` decimal(20,2) NOT NULL, `iva` decimal(20,2) NOT NULL,
`total` decimal(20,2) NOT NULL, `medio_pago` varchar(2000) NOT NULL,
`digitos` varchar(100) NOT NULL, `operaciones` int(10) NOT NULL,
`activa` varchar(2) NOT NULL, `movimiento` varchar(45) NOT NULL,
`parcialidades` varchar(100) NOT NULL, `monto_bruto` decimal(20,2)
NOT NULL, `billid` varchar(45) NOT NULL, `serie` varchar(2)
DEFAULT NULL, `folio` int(10) DEFAULT NULL, `uuid` varchar(45)
DEFAULT NULL, PRIMARY KEY (`id`), KEY `motors`
(`billid`,`id_fechas`,`activa`) ) ENGINE=MyISAM AUTO_INCREMENT=511483
DEFAULT CHARSET=latin1;
I changed the MySQL server from 5.1 (32 Bits) to 5.6 (64 Bits) and restored all my tables but I´m having problems with this query:
SELECT a.custid,
a.monto_facturado,
a.billid,
a.fecha,
b.id,
b.fecha_inicial
FROM facturacion_2012_drm_base a,
facturacion_2012_drm_cortes b
WHERE a.custid = ANY (SELECT custid
FROM facturacion_motors_pendientes
WHERE situacion = 'no facturado')
AND a.billid <> ALL (SELECT billid
FROM facturacion_2012_drm_emitidas
WHERE activa = 'SI')
AND a.fecha BETWEEN b.fecha_inicial AND b.fecha_final
AND a.documento = 'FA'
AND Year(a.fecha) = Year(Curdate())
GROUP BY a.billid
Since the server change, the query never finish, showing the message "Query is being executed..."
Anybody knows why this is happening?
At the very least you have indexing problems:
On facturacion_2012_drm_emitidas you filter by activa but do not have an index that can be used for this
On facturacion_2012_drm_base you don't have an index for fecha or documento that can be used
On facturacion_2012_drm_cortes you don't have an index for fecha_inicial or fecha_final
I don't know if you have index problems on facturacion_motors_pendientes because you did not include DDL for it.
Make sure you have the proper indexes for your query and then see what happens. What is happening now is that you have a complex join with subqueries and basically none of it is utilizing indexes, requiring you to execute full table scans on all tables involved.
You also might consider converting these tables to InnoDB, as that is the preferred table type in 5.6. This is of course unless you need certain MyISAM functionality on these tables (like full text search).