Bug #47330 | Slow query with left join and having. | ||
---|---|---|---|
Submitted: | 15 Sep 2009 15:39 | Modified: | 23 Sep 2009 9:42 |
Reporter: | Peter Szekvolgyi | Email Updates: | |
Status: | Verified | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S5 (Performance) |
Version: | 5.0.77, 5.1.34, 5.1.37 | OS: | Linux (Debian x64) |
Assigned to: | CPU Architecture: | Any | |
Tags: | regression |
[15 Sep 2009 15:39]
Peter Szekvolgyi
[15 Sep 2009 16:42]
Valeriy Kravchuk
Thank you for the problem report. What about `egy2`'s content? Can you send a dump of its data? Had you tried to change engine for `egy2` to MyISAM? I wonder if you'll see any difference in this case.
[15 Sep 2009 18:10]
Peter Szekvolgyi
Yes, i tried MyISAM engine. The fast query speed is same, the slow is 1.5-2 sec. Tomorrow i will put dump to web, but it's 70-80 MB. Or i try to write a script what generates data to egy2 table.
[15 Sep 2009 18:46]
Valeriy Kravchuk
Script is OK, as soon as it adds data that allows to repeat this problem every time.
[16 Sep 2009 11:24]
Peter Szekvolgyi
I changed ET table szlaaz from bigint(20) to mediumint(9). The slow and the fast query speed good, same and explain is same too, but in the originally query et data came from a subquery and it return bigint(20). Can I change the subquery data records type? I will attach the generator script soon.
[22 Sep 2009 7:05]
Peter Szekvolgyi
Data create script with table create
Attachment: generate.sh (application/octet-stream, text), 3.04 KiB.
[22 Sep 2009 7:09]
Peter Szekvolgyi
I attached the data generator script for linux/unix. Use: ./generate | mysql test The run time of this script is long. ( It's generate over 2 million records. ) And default it's run create table for et and egy2 table. If it exist drop these table and create!
[22 Sep 2009 8:14]
Peter Szekvolgyi
After the generator script done please run: update egy2 SET szaz=1,szaz=19868 limit 214121; Without this both query speed good.
[23 Sep 2009 7:17]
Valeriy Kravchuk
Verified just as described using your script and steps described: openxs@suse:/home2/openxs/dbs/5.0> sh /home2/openxs/generate.sh | bin/mysql -uroot test openxs@suse:/home2/openxs/dbs/5.0> bin/mysql -uroot test Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3 Server version: 5.0.86-debug Source distribution Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> update egy2 SET szaz=1,szaz=19868 limit 214121; Query OK, 214118 rows affected (25 min 10.78 sec) Rows matched: 214121 Changed: 214118 Warnings: 0 mysql> explain select et.raz, 0 as tnemzarttdt, 0 as zaro from et left join egy2 es on et.tip = 1 and et.mad=es.datum and es.raz=et.raz and es.szlaaz=et.szlaaz and et.szaz=es.szaz group by et.raz having ( 1=1 ); +----+-------------+-------+--------+-----------------------------+-------+---------+-------------------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+-----------------------------+-------+---------+-------------------------+------+-------------+ | 1 | SIMPLE | et | system | NULL | NULL | NULL | NULL | 1 | | | 1 | SIMPLE | es | ref | raz,szaz,datum,szlaaz,raz_2 | raz_2 | 14 | const,const,const,const | 206 | Using index | +----+-------------+-------+--------+-----------------------------+-------+---------+-------------------------+------+-------------+ 2 rows in set (0.01 sec) mysql> explain select et.raz, 0 as tnemzarttdt, 0 as zaro from et -> left join egy2 es on et.tip = 1 and et.mad=es.datum and es.raz=et.raz and -> et.szlaaz=es.szlaaz and et.szaz=es.szaz -> group by et.raz -> having ( 1=1 ); +----+-------------+-------+--------+-----------------------------+--------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+-----------------------------+--------+---------+-------+------+-------+ | 1 | SIMPLE | et | system | NULL | NULL | NULL | NULL | 1 | | | 1 | SIMPLE | es | ref | raz,szaz,datum,szlaaz,raz_2 | szlaaz | 3 | const | 10 | | +----+-------------+-------+--------+-----------------------------+--------+---------+-------+------+-------+ 2 rows in set (0.00 sec) mysql> select et.raz, 0 as tnemzarttdt, 0 as zaro from et left join egy2 es on et.tip = 1 and et.mad=es.datum and es.raz=et.raz and et.szlaaz=es.szlaaz and et.szaz=es.szaz group by et.raz having ( 1=1 ); +-----+-------------+------+ | raz | tnemzarttdt | zaro | +-----+-------------+------+ | 11 | 0 | 0 | +-----+-------------+------+ 1 row in set (3 min 4.51 sec) Here we have the problem. egy2 table is big enough: mysql> show table status like 'egy2'; +------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-------------------+----------+----------------+-----------------------+ | Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment | +------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-------------------+----------+----------------+-----------------------+ | egy2 | InnoDB | 10 | Compact | 2250558 | 39 | 88702976 | 0 | 287326208 | 0 | 2516587 | 2009-12-28 21:19:24 | NULL | NULL | latin1_swedish_ci | NULL | | InnoDB free: 16384 kB | +------+--------+---------+------------+---------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-------------------+----------+----------------+-----------------------+ 1 row in set (4.99 sec) But the problem is NOT about bad statistics from InnoDB, as it is repeatable with MyISAM: mysql> alter table egy2 engine=MyISAM; Query OK, 2250084 rows affected (4 min 3.52 sec) Records: 2250084 Duplicates: 0 Warnings: 0 mysql> select et.raz, 0 as tnemzarttdt, 0 as zaro from et left join egy2 es on et.tip = 1 and et.mad=es.datum and es.raz=et.raz and et.szlaaz=es.szlaaz and et.szaz=es.szaz group by et.raz having ( 1=1 ); +-----+-------------+------+ | raz | tnemzarttdt | zaro | +-----+-------------+------+ | 11 | 0 | 0 | +-----+-------------+------+ 1 row in set (14.24 sec) mysql> explain select et.raz, 0 as tnemzarttdt, 0 as zaro from et left join egy2 es on et.tip = 1 and et.mad=es.datum and es.raz=et.raz and et.szlaaz=es.szlaaz and et.szaz=es.szaz group by et.raz having ( 1=1 ); +----+-------------+-------+--------+-----------------------------+--------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+-----------------------------+--------+---------+-------+------+-------+ | 1 | SIMPLE | et | system | NULL | NULL | NULL | NULL | 1 | | | 1 | SIMPLE | es | ref | raz,szaz,datum,szlaaz,raz_2 | szlaaz | 3 | const | 10 | | +----+-------------+-------+--------+-----------------------------+--------+---------+-------+------+-------+ 2 rows in set (0.01 sec) Workaround: use FORCE INDEX(raz_2).
[23 Sep 2009 9:36]
Peter Szekvolgyi
If i remove having ( 1 = 1 ) or change et.szlaaz=es.szlaaz to es.szlaaz=et.szlaaz why fast? So it's not an optimizer bug? In MySql 4.1.15 with MyISAM both query are fast.
[23 Sep 2009 9:42]
Peter Szekvolgyi
Sorry, i read it was verified.