# Bad performance with simple join

**URL:** <https://forums.percona.com/t/bad-performance-with-simple-join/683>\
**Category:** Other MySQL® Questions\
**Created:** [March 24, 2008, 3:51pm UTC](https://forums.percona.com/t/bad-performance-with-simple-join/683 "2008-03-24T15:51:56Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![kenny01](https://avatars.discourse-cdn.com/v4/letter/k/c6cbf5/32.png) [@kenny01](https://forums.percona.com/u/kenny01)\
**Post date:** [March 24, 2008, 3:51pm UTC](https://forums.percona.com/t/bad-performance-with-simple-join/683/1 "2008-03-24T15:51:56Z")

</div>

Hi all,

I am having issues with the following query, Its very slow (about 3 minutes to complete for just 2 days).

Could somebody point where is the problem and how I can re-write the query so its much faster?  
I can’t see why its going so slow!!

Note: All the tables queried have the same format, as all of them are statistics from different clusters for the same application.

The server is a large server: Solaris 10, 8 AMD dual core CPU and 32 GB RAM. Two raid SCSI disks. But during the query I can see just 5% CPU usage!!

explain extended  
SELECT  
UPPER(CAST(date\_format(`cluster2-transactions_per_second`.Da te\_Time, ‘%Y-%m-%d %H:%i’) as datetime)) as “Date\_Time”,  
SUM(DISTINCT (`cluster2-transactions_per_second`.`mail_transactions` )) AS cluster2\_mo\_attempts,  
SUM(DISTINCT (`cluster3-transactions_per_second`.`mail_transactions` )) AS cluster3\_mo\_attempts,  
SUM(DISTINCT (`cluster4-transactions_per_second`.`mail_transactions` )) AS cluster4\_mo\_attempts,  
SUM(DISTINCT (`cluster5-transactions_per_second`.`mail_transactions` )) AS cluster5\_mo\_attempts,  
SUM(DISTINCT (`cluster6-transactions_per_second`.`mail_transactions` )) AS cluster6\_mo\_attempts,  
SUM(DISTINCT (`cluster7-transactions_per_second`.`mail_transactions` )) AS cluster7\_mo\_attempts  
FROM  
`cluster2-transactions_per_second` force index (date\_index),  
`cluster3-transactions_per_second` force index (date\_index),  
`cluster4-transactions_per_second` force index (date\_index),  
`cluster5-transactions_per_second` force index (date\_index),  
`cluster6-transactions_per_second` force index (date\_index),  
`cluster7-transactions_per_second` force index (date\_index)  
WHERE  
`cluster2-transactions_per_second`.Date\_Time=`cluster3-trans actions_per_second`.Date\_Time AND  
`cluster2-transactions_per_second`.Date\_Time=`cluster4-trans actions_per_second`.Date\_Time AND  
`cluster2-transactions_per_second`.Date\_Time=`cluster5-trans actions_per_second`.Date\_Time AND  
`cluster2-transactions_per_second`.Date\_Time=`cluster6-trans actions_per_second`.Date\_Time AND  
`cluster2-transactions_per_second`.Date\_Time=`cluster7-trans actions_per_second`.Date\_Time AND  
`cluster2-transactions_per_second`.Date\_Time \< ‘2008-10-01 23:55’ AND  
`cluster2-transactions_per_second`.Date\_Time \> ‘2008-03-19 23:55’  
group by `cluster2-transactions_per_second`.Date\_Time order by `cluster2-transactions_per_second`.Date\_Time  
\G;

\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 1. row \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
id: 1  
select\_type: SIMPLE  
table: cluster2-transactions\_per\_second  
type: range  
possible\_keys: date\_index  
key: date\_index  
key\_len: 22  
ref: NULL  
rows: 1993  
Extra: Using where  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 2. row \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
id: 1  
select\_type: SIMPLE  
table: cluster3-transactions\_per\_second  
type: ref  
possible\_keys: date\_index  
key: date\_index  
key\_len: 22  
ref: load\_test\_db.cluster2-transactions\_per\_second.Date\_Time  
rows: 19  
Extra:  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 3. row \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
id: 1  
select\_type: SIMPLE  
table: cluster4-transactions\_per\_second  
type: ref  
possible\_keys: date\_index  
key: date\_index  
key\_len: 22  
ref: load\_test\_db.cluster2-transactions\_per\_second.Date\_Time  
rows: 19  
Extra:  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 4. row \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
id: 1  
select\_type: SIMPLE  
table: cluster5-transactions\_per\_second  
type: ref  
possible\_keys: date\_index  
key: date\_index  
key\_len: 22  
ref: load\_test\_db.cluster4-transactions\_per\_second.Date\_Time  
rows: 19  
Extra: Using where  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 5. row \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
id: 1  
select\_type: SIMPLE  
table: cluster6-transactions\_per\_second  
type: ref  
possible\_keys: date\_index  
key: date\_index  
key\_len: 22  
ref: load\_test\_db.cluster5-transactions\_per\_second.Date\_Time  
rows: 19  
Extra: Using where  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 6. row \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
id: 1  
select\_type: SIMPLE  
table: cluster7-transactions\_per\_second  
type: ref  
possible\_keys: date\_index  
key: date\_index  
key\_len: 22  
ref: load\_test\_db.cluster2-transactions\_per\_second.Date\_Time  
rows: 19  
Extra:  
6 rows in set, 1 warning (0.00 sec)

mysql\> describe `cluster2-transactions_per_second`;  
±------------------±-------------±-----±----±---------- ----------±------+  
| Field | Type | Null | Key | Default | Extra |  
±------------------±-------------±-----±----±---------- ----------±------+  
| Date\_Time | varchar(20) | NO | MUL | 0000-00-00 00:00:00 | |  
| HostName | varchar(255) | NO | MUL | | |  
| mail\_transactions | double | YES | | NULL | |  
| CPU\_usage | double | YES | | NULL | |  
±------------------±-------------±-----±----±---------- ----------±------+  
4 rows in set (0.00 sec)

mysql\> describe `cluster3-transactions_per_second`;  
±------------------±-------------±-----±----±---------- ----------±------+  
| Field | Type | Null | Key | Default | Extra |  
±------------------±-------------±-----±----±---------- ----------±------+  
| Date\_Time | varchar(20) | NO | MUL | 0000-00-00 00:00:00 | |  
| HostName | varchar(255) | NO | MUL | | |  
| mail\_transactions | double | YES | | NULL | |  
| CPU\_usage | double | YES | | NULL | |  
±------------------±-------------±-----±----±---------- ----------±------+  
4 rows in set (0.00 sec)

mysql\> describe `cluster4-transactions_per_second`;  
±------------------±-------------±-----±----±---------- ----------±------+  
| Field | Type | Null | Key | Default | Extra |  
±------------------±-------------±-----±----±---------- ----------±------+  
| Date\_Time | varchar(20) | NO | MUL | 0000-00-00 00:00:00 | |  
| HostName | varchar(255) | NO | MUL | | |  
| mail\_transactions | double | YES | | NULL | |  
| CPU\_usage | double | YES | | NULL | |  
±------------------±-------------±-----±----±---------- ----------±------+  
4 rows in set (0.00 sec)

mysql\> describe `cluster5-transactions_per_second`;  
±------------------±-------------±-----±----±---------- ----------±------+  
| Field | Type | Null | Key | Default | Extra |  
±------------------±-------------±-----±----±---------- ----------±------+  
| Date\_Time | varchar(20) | NO | MUL | 0000-00-00 00:00:00 | |  
| HostName | varchar(255) | NO | MUL | | |  
| mail\_transactions | double | YES | | NULL | |  
| CPU\_usage | double | YES | | NULL | |  
±------------------±-------------±-----±----±---------- ----------±------+  
4 rows in set (0.00 sec)

mysql\> describe `cluster6-transactions_per_second`;  
±------------------±-------------±-----±----±---------- ----------±------+  
| Field | Type | Null | Key | Default | Extra |  
±------------------±-------------±-----±----±---------- ----------±------+  
| Date\_Time | varchar(20) | NO | MUL | 0000-00-00 00:00:00 | |  
| HostName | varchar(255) | NO | MUL | | |  
| mail\_transactions | double | YES | | NULL | |  
| CPU\_usage | double | YES | | NULL | |  
±------------------±-------------±-----±----±---------- ----------±------+  
4 rows in set (0.00 sec)

mysql\> describe `cluster7-transactions_per_second`;  
±------------------±-------------±-----±----±---------- ----------±------+  
| Field | Type | Null | Key | Default | Extra |  
±------------------±-------------±-----±----±---------- ----------±------+  
| Date\_Time | varchar(20) | NO | MUL | 0000-00-00 00:00:00 | |  
| HostName | varchar(255) | NO | MUL | | |  
| mail\_transactions | double | YES | | NULL | |  
| CPU\_usage | double | YES | | NULL | |  
±------------------±-------------±-----±----±---------- ----------±------+  
4 rows in set (0.00 sec)

mysql\> select count(_) from `cluster2-transactions_per_second`;  
±---------+  
| count(_) |  
±---------+  
| 183382 |  
±---------+

mysql\> select count(_) from `cluster3-transactions_per_second`;  
±---------+  
| count(_) |  
±---------+  
| 183382 |  
±---------+

mysql\> show create table `cluster2-transactions_per_second`;  
±----------------------------------------------------±---- ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ----------------------------------------------------------+  
| Table | Create Table |  
±----------------------------------------------------±---- ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ----------------------------------------------------------+  
| cluster2-transactions\_per\_second | CREATE TABLE `cluster2-transactions_per_second`(  
`Date_Time` varchar(20) NOT NULL default ‘0000-00-00 00:00:00’,  
`HostName` varchar(255) NOT NULL default ‘’,  
`mail_transactions` double default NULL,  
`CPU_usage` double default NULL,  
KEY `date_index` (`Date_Time`),  
KEY `hostname_index` (`HostName`)  
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |  
±----------------------------------------------------±---- ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ----------------------------------------------------------+  
1 row in set (0.00 sec)

mysql\> show variables;  
±--------------------------------±------------------------ ---------------+  
| Variable\_name | Value |  
±--------------------------------±------------------------ ---------------+  
| auto\_increment\_increment | 1 |  
| auto\_increment\_offset | 1 |  
| automatic\_sp\_privileges | ON |  
| back\_log | 50 |  
| basedir | /opt/mysql/mysql/ |  
| binlog\_cache\_size | 2097152 |  
| bulk\_insert\_buffer\_size | 134217728 |  
| character\_set\_client | latin1 |  
| character\_set\_connection | latin1 |  
| character\_set\_database | latin1 |  
| character\_set\_filesystem | binary |  
| character\_set\_results | latin1 |  
| character\_set\_server | latin1 |  
| character\_set\_system | utf8 |  
| character\_sets\_dir | /opt/mysql/mysql/share/mysql/charsets/ |  
| collation\_connection | latin1\_swedish\_ci |  
| collation\_database | latin1\_swedish\_ci |  
| collation\_server | latin1\_swedish\_ci |  
| completion\_type | 0 |  
| concurrent\_insert | 1 |  
| connect\_timeout | 30 |  
| datadir | /var/lib/mysql/ |  
| date\_format | %Y-%m-%d |  
| datetime\_format | %Y-%m-%d %H:%i:%s |  
| default\_week\_format | 0 |  
| delay\_key\_write | ON |  
| delayed\_insert\_limit | 100 |  
| delayed\_insert\_timeout | 300 |  
| delayed\_queue\_size | 1000 |  
| div\_precision\_increment | 4 |  
| keep\_files\_on\_create | OFF |  
| engine\_condition\_pushdown | OFF |  
| expire\_logs\_days | 0 |  
| flush | OFF |  
| flush\_time | 0 |  
| ft\_boolean\_syntax | + -\>\<()~\*:“”&| |  
| ft\_max\_word\_len | 84 |  
| ft\_min\_word\_len | 4 |  
| ft\_query\_expansion\_limit | 20 |  
| ft\_stopword\_file | (built-in) |  
| group\_concat\_max\_len | 1024 |  
| have\_archive | YES |  
| have\_bdb | NO |  
| have\_blackhole\_engine | YES |  
| have\_compress | YES |  
| have\_crypt | YES |  
| have\_csv | YES |  
| have\_dynamic\_loading | YES |  
| have\_example\_engine | YES |  
| have\_federated\_engine | YES |  
| have\_geometry | YES |  
| have\_innodb | DISABLED |  
| have\_isam | NO |  
| have\_merge\_engine | YES |  
| have\_ndbcluster | NO |  
| have\_openssl | DISABLED |  
| have\_ssl | DISABLED |  
| have\_query\_cache | YES |  
| have\_raid | NO |  
| have\_rtree\_keys | YES |  
| have\_symlink | YES |  
| hostname | mdbserver |  
| init\_connect | |  
| init\_file | |  
| init\_slave | |  
| innodb\_additional\_mem\_pool\_size | 16777216 |  
| innodb\_autoextend\_increment | 8 |  
| innodb\_buffer\_pool\_awe\_mem\_mb | 0 |  
| innodb\_buffer\_pool\_size | 2147483648 |  
| innodb\_checksums | ON |  
| innodb\_commit\_concurrency | 0 |  
| innodb\_concurrency\_tickets | 500 |  
| innodb\_data\_file\_path | ibdata1:200M:autoextend |  
| innodb\_data\_home\_dir | |  
| innodb\_adaptive\_hash\_index | ON |  
| innodb\_doublewrite | ON |  
| innodb\_fast\_shutdown | 1 |  
| innodb\_file\_io\_threads | 4 |  
| innodb\_file\_per\_table | OFF |  
| innodb\_flush\_log\_at\_trx\_commit | 1 |  
| innodb\_flush\_method | |  
| innodb\_force\_recovery | 0 |  
| innodb\_lock\_wait\_timeout | 120 |  
| innodb\_locks\_unsafe\_for\_binlog | OFF |  
| innodb\_log\_arch\_dir | |  
| innodb\_log\_archive | OFF |  
| innodb\_log\_buffer\_size | 8388608 |  
| innodb\_log\_file\_size | 268435456 |  
| innodb\_log\_files\_in\_group | 3 |  
| innodb\_log\_group\_home\_dir | ./ |  
| innodb\_max\_dirty\_pages\_pct | 90 |  
| innodb\_max\_purge\_lag | 0 |  
| innodb\_mirrored\_log\_groups | 1 |  
| innodb\_open\_files | 300 |  
| innodb\_rollback\_on\_timeout | OFF |  
| innodb\_support\_xa | ON |  
| innodb\_sync\_spin\_loops | 20 |  
| innodb\_table\_locks | ON |  
| innodb\_thread\_concurrency | 16 |  
| innodb\_thread\_sleep\_delay | 10000 |  
| interactive\_timeout | 28800 |  
| join\_buffer\_size | 1048571904 |  
| key\_buffer\_size | 314572800 |  
| key\_cache\_age\_threshold | 300 |  
| key\_cache\_block\_size | 1024 |  
| key\_cache\_division\_limit | 100 |  
| language | /opt/mysql/mysql/share/mysql/english/ |  
| large\_files\_support | ON |  
| large\_page\_size | 0 |  
| large\_pages | OFF |  
| lc\_time\_names | en\_US |  
| license | GPL |  
| local\_infile | ON |  
| locked\_in\_memory | OFF |  
| log | OFF |  
| log\_bin | ON |  
| log\_bin\_trust\_function\_creators | OFF |  
| log\_error | |  
| log\_queries\_not\_using\_indexes | OFF |  
| log\_slave\_updates | OFF |  
| log\_slow\_queries | ON |  
| log\_warnings | 2 |  
| long\_query\_time | 2 |  
| low\_priority\_updates | OFF |  
| lower\_case\_file\_system | OFF |  
| lower\_case\_table\_names | 0 |  
| max\_allowed\_packet | 67107840 |  
| max\_binlog\_cache\_size | 4294967295 |  
| max\_binlog\_size | 1073741824 |  
| max\_connect\_errors | 100000000 |  
| max\_connections | 2000 |  
| max\_delayed\_threads | 20 |  
| max\_error\_count | 64 |  
| max\_heap\_table\_size | 314572800 |  
| max\_insert\_delayed\_threads | 20 |  
| max\_join\_size | 18446744073709551615 |  
| max\_length\_for\_sort\_data | 1024 |  
| max\_prepared\_stmt\_count | 16382 |  
| max\_relay\_log\_size | 0 |  
| max\_seeks\_for\_key | 4294967295 |  
| max\_sort\_length | 1024 |  
| max\_sp\_recursion\_depth | 0 |  
| max\_tmp\_tables | 32 |  
| max\_user\_connections | 0 |  
| max\_write\_lock\_count | 4294967295 |  
| multi\_range\_count | 256 |  
| myisam\_data\_pointer\_size | 6 |  
| myisam\_max\_sort\_file\_size | 10737418240 |  
| myisam\_recover\_options | DEFAULT |  
| myisam\_repair\_threads | 1 |  
| myisam\_sort\_buffer\_size | 104857600 |  
| myisam\_stats\_method | nulls\_unequal |  
| net\_buffer\_length | 16384 |  
| net\_read\_timeout | 30 |  
| net\_retry\_count | 10 |  
| net\_write\_timeout | 60 |  
| new | OFF |  
| old\_passwords | OFF |  
| open\_files\_limit | 26106 |  
| optimizer\_prune\_level | 1 |  
| optimizer\_search\_depth | 62 |  
| pid\_file | /var/lib/mysql/mdbserver.pid |  
| port | 3306 |  
| preload\_buffer\_size | 32768 |  
| protocol\_version | 10 |  
| query\_alloc\_block\_size | 8192 |  
| query\_cache\_limit | 2097152 |  
| query\_cache\_min\_res\_unit | 4096 |  
| query\_cache\_size | 134217728 |  
| query\_cache\_type | ON |  
| query\_cache\_wlock\_invalidate | OFF |  
| query\_prealloc\_size | 8192 |  
| range\_alloc\_block\_size | 2048 |  
| read\_buffer\_size | 524283904 |  
| read\_only | OFF |  
| read\_rnd\_buffer\_size | 209711104 |  
| relay\_log | |  
| relay\_log\_index | |  
| relay\_log\_info\_file | relay-log.info |  
| relay\_log\_purge | ON |  
| relay\_log\_space\_limit | 0 |  
| rpl\_recovery\_rank | 0 |  
| secure\_auth | OFF |  
| secure\_file\_priv | |  
| server\_id | 1 |  
| skip\_external\_locking | ON |  
| skip\_networking | OFF |  
| skip\_show\_database | OFF |  
| slave\_compressed\_protocol | OFF |  
| slave\_load\_tmpdir | /tmp/ |  
| slave\_net\_timeout | 3600 |  
| slave\_skip\_errors | OFF |  
| slave\_transaction\_retries | 10 |  
| slow\_launch\_time | 2 |  
| socket | /tmp/mysql.sock |  
| sort\_buffer\_size | 629145592 |  
| sql\_big\_selects | ON |  
| sql\_mode | |  
| sql\_notes | ON |  
| sql\_warnings | OFF |  
| ssl\_ca | |  
| ssl\_capath | |  
| ssl\_cert | |  
| ssl\_cipher | |  
| ssl\_key | |  
| storage\_engine | MyISAM |  
| sync\_binlog | 0 |  
| sync\_frm | ON |  
| system\_time\_zone | GMT |  
| table\_cache | 12048 |  
| table\_lock\_wait\_timeout | 50 |  
| table\_type | MyISAM |  
| thread\_cache\_size | 8 |  
| thread\_concurrency | 16 |  
| thread\_stack | 196608 |  
| time\_format | %H:%i:%s |  
| time\_zone | SYSTEM |  
| timed\_mutexes | OFF |  
| tmp\_table\_size | 1048576000 |  
| tmpdir | /tmp |  
| transaction\_alloc\_block\_size | 8192 |  
| transaction\_prealloc\_size | 4096 |  
| tx\_isolation | REPEATABLE-READ |  
| updatable\_views\_with\_limit | YES |  
| version | 5.0.52-enterprise-gpl-log |  
| version\_comment | MySQL Enterprise Server (GPL) |  
| version\_compile\_machine | i386 |  
| version\_compile\_os | pc-solaris2.10 |  
| wait\_timeout | 28800 |  
±--------------------------------±------------------------ ---------------+

---

<div class="post-metadata">

**Author:** ![sterin](https://avatars.discourse-cdn.com/v4/letter/s/3ab097/32.png) [@sterin](https://forums.percona.com/u/sterin)\
**Post date:** [March 25, 2008, 8:44am UTC](https://forums.percona.com/t/bad-performance-with-simple-join/683/2 "2008-03-25T08:44:11Z")

</div>

| [B]Quote:[/B] |
| 

… 8 AMD dual core CPU …

 |

Does that appear to the OS as 16 CPU's?

MySQL executes a query in only _one_ thread.  
Which means that if you have a CPU intensive query it will only be able to use 100/16=6.25 percent cpu usage on a 16 way machine.

But regardless of that it seems like a long time for that query so here are some thoughts:  
1.  
Why is your “Date\_Time” a VARCHAR(20) and not a real DATETIME?  
Generally you should try to avoid joining on large fields so just by changing this to a DATETIME you will instead join on a 8 byte field instead of a 22 byte field as you have today.  
The difference is almost 1/3 in index size.

1. 

Why are you using SUM([B]DISTINCT/B)?  
Since I don’t really know your table structure I can’t really understand. But the SUM(DISTINCT()) combination sounds a bit strange, if you had been using COUNT(DISTINCT()) I could have understood it better since you are then counting the distinct values. But the SUM means that you are summarizing on a filtered value where if two mail\_transactions happen to have the same value you are filtering it away.  
Do you have duplicate entries in the tables that you want to get rid of?

1. 

Just to rule this out, do you have any IO load or swapping taking place during the execution of this query?

BTW:  
I applauding your excellent post, a wealth of information which makes trying to figure out your problem so much easier. )

---

<div class="post-metadata">

**Author:** ![safari](https://avatars.discourse-cdn.com/v4/letter/s/838e76/32.png) [@safari](https://forums.percona.com/u/safari)\
**Post date:** [March 25, 2008, 10:54am UTC](https://forums.percona.com/t/bad-performance-with-simple-join/683/3 "2008-03-25T10:54:12Z")

</div>

My concern is about variables,

- join\_buffer\_size = 1048571904 ~ 1000M
- key\_buffer\_size = 314572800 ~ 300M
- read\_buffer\_size = 524283904 ~ 500M
- read\_rnd\_buffer\_size = 209711104 ~ 200M

IMHO, join, read, and read\_rnd buffer size is too large; besides that key\_buffer\_size is small comparing to the MyISAM tables size.

---

<div class="post-metadata">

**Author:** ![sterin](https://avatars.discourse-cdn.com/v4/letter/s/3ab097/32.png) [@sterin](https://forums.percona.com/u/sterin)\
**Post date:** [March 26, 2008, 6:49pm UTC](https://forums.percona.com/t/bad-performance-with-simple-join/683/4 "2008-03-26T18:49:53Z")

</div>

1. 

Your Date\_Time string is in the right format.  
It’s just that the column is defined in the wrong format in the table.  
A string like ‘2008-10-01 23:55:00’ is the ISO standard format to represent a date and time.  
And this is the format that MySQL takes/returns when you insert/select times into/from a DATETIME column.  
So you can without any changes to the application make an alteration of the table so that this column is a DATETIME and the application will not know the difference.  
Plus you can get rid of the very ugly cast(date\_format()) stuff that you have in this query on this column.

1. 

Don’t use double to store decimal values. Use the NUMERIC type instead.  
In your table both the CPU and nr of transactions are created as double and double is per definition an approximation of an value.  
For example in your case the CPU load always seems to be two digits and one decimal, so type should be NUMERIC(3,1). that means the largest value can be 99.9 and the smallest value can be -99.9.

The same goes for the transactions only this values seems to be 2 digits and 3 decimals so NUMERIC(5,3) could seem appropriate for this (unless there is a chance that it races above 99.999 transactions then a NUMERIC(6,3) is more appropriate.  
Here’s an example of how I defined the tables.

CREATE TABLE `cluster2-transactions_per_second` ( `Date_Time` datetime NOT NULL DEFAULT ‘0000-00-00 00:00:00’, `HostName` varchar(255) NOT NULL DEFAULT ‘’, `mail_transactions` decimal(6,3) DEFAULT NULL, `CPU_usage` decimal(3,1) DEFAULT NULL, KEY `c2_ix_datetime_trans` (`Date_Time`,`mail_transactions`), KEY `hostname_index` (`HostName`)) ENGINE=MyISAM DEFAULT CHARSET=latin1

1. 

I recommend avoid using a subtraction “-” sign in a table name.  
That is what is forcing you to use back-ticks around the table names.  
If you want separation for readability stick to the underscore sign.  
( I still used it in the posts here on this post since you have it in your database, but you should avoid it).

1. 

Now I understand why you had a SUM(DISTINCT…) but the underlying problem is a cross join. And that is solved by the query below in point 5.

But the problem with your SUM(DISTINCT …) is that if you have these rows in your table:

2008-03-20 18:30:00,cluster2\_node1,52.902,14.22008-03-20 18:30:00,cluster2\_node2,53.312,15.42008-03-20 18:30:00,cluster2\_node3,55.872,15.12008-03-20 18:30:00,cluster2\_node4,53.312,15.02008-03-20 18:30:00,cluster2\_node5,44.333,14.9

Notice how row 2 and 4 just happen to have the same nr of transactions.  
Then the DISTINCT means that one of these rows will be filtered away and then you will only calculate the sum of the 4 remaining rows. And suddenly you have dropped 1/5 of the transactions.  
That is why I was questioning the SUM(DISTINCT …) in the first place.

1. 

I rewrote your query quite a lot because your query was performing a cross join since you had more than one row with the same Date\_Time value per table.  
Your DISTINCTs was covering this up but it forced the DBMS to do an enormous amount of unnecessary work since the temporary table would be so huge.

My query is utilizing sub-selects and aliases and dropped the DISTINCT:

SELECT ctime.Date\_Time as “Date\_Time”, ( select SUM(c2.`mail_transactions`) FROM `cluster2-transactions_per_second` c2 WHERE ctime.Date\_Time = c2.Date\_Time) AS cluster2\_mo\_attempts, (select SUM(c3.`mail_transactions`) FROM `cluster3-transactions_per_second` c3 WHERE ctime.Date\_Time = c3.Date\_Time) AS cluster3\_mo\_attempts, (select SUM(c4.`mail_transactions`) FROM `cluster4-transactions_per_second` c4 WHERE ctime.Date\_Time = c4.Date\_Time) AS cluster4\_mo\_attempts, (select SUM(c5.`mail_transactions`) FROM `cluster5-transactions_per_second` c5 WHERE ctime.Date\_Time = c5.Date\_Time) AS cluster5\_mo\_attempts, (select SUM(c6.`mail_transactions`) FROM `cluster6-transactions_per_second` c6 WHERE ctime.Date\_Time = c6.Date\_Time) AS cluster6\_mo\_attempts, (select SUM(c7.`mail_transactions`) FROM `cluster7-transactions_per_second` c7 WHERE ctime.Date\_Time = c7.Date\_Time) AS cluster7\_mo\_attemptsFROM (SELECT DISTINCT Date\_Time FROM `cluster2-transactions_per_second` c WHERE c.Date\_Time \< ‘2008-10-01 23:55:00’ AND c.Date\_Time \> ‘2008-03-19 23:55:00’ ) ctimeORDER BY ctime.Date\_Time;

This query first creates a temp table ctime which only contains unique time values.  
Then it performs the subselects in the SELECT part matching the current unique time value and summarizes these 5 values.  
That way you will only have 5 records at a time for the subselects to summarize.

1. 

To tweak that little extre of speed you can add these combined index on all tables so that MySQL doesn’t have to read from the table at all to execute this query.

ALTER TABLE `cluster2-transactions_per_second` ADD INDEX c2\_ix\_datetime\_trans(Date\_Time, mail\_transactions);ALTER TABLE `cluster3-transactions_per_second` ADD INDEX c3\_ix\_datetime\_trans(Date\_Time, mail\_transactions);ALTER TABLE `cluster4-transactions_per_second` ADD INDEX c4\_ix\_datetime\_trans(Date\_Time, mail\_transactions);ALTER TABLE `cluster5-transactions_per_second` ADD INDEX c5\_ix\_datetime\_trans(Date\_Time, mail\_transactions);ALTER TABLE `cluster6-transactions_per_second` ADD INDEX c6\_ix\_datetime\_trans(Date\_Time, mail\_transactions);ALTER TABLE `cluster7-transactions_per_second` ADD INDEX c7\_ix\_datetime\_trans(Date\_Time, mail\_transactions);

It got to be a long post with a lot of pointers, but the main one is the different structure of the query so that it doesn’t perform a cross join as it did before.  
The other ones are recommendations.

Please let me know what kind of speed increase you got.

Cheers!

---

<div class="post-metadata">

**Author:** ![kenny01](https://avatars.discourse-cdn.com/v4/letter/k/c6cbf5/32.png) [@kenny01](https://forums.percona.com/u/kenny01)\
**Post date:** [March 27, 2008, 9:53am UTC](https://forums.percona.com/t/bad-performance-with-simple-join/683/5 "2008-03-27T09:53:16Z")

</div>

Hi sterin,

First of all, thanks for your wide and clear response.

The query you proposed improved the response time from minutes to few seconds!!!

Thanks again, thats exactly the kind of feedback I was looking for.

By Reading your query I can see what the optimizer and MySQL engine was performing wrong and how to work around this.

Also the workload seems to spread better on the CPU.

I would like to thank you once more for your response.

---

<div class="post-metadata">

**Author:** ![sterin](https://avatars.discourse-cdn.com/v4/letter/s/3ab097/32.png) [@sterin](https://forums.percona.com/u/sterin)\
**Post date:** [March 27, 2008, 10:04am UTC](https://forums.percona.com/t/bad-performance-with-simple-join/683/6 "2008-03-27T10:04:22Z")

</div>

My pleasure, nice to know that I have made a difference in the world. )

Take care!
