Bug #2104 | after deleting row index got fragmented | ||
---|---|---|---|
Submitted: | 12 Dec 2003 6:02 | Modified: | 30 Jan 2004 5:45 |
Reporter: | Tom Zlos | Email Updates: | |
Status: | Can't repeat | Impact on me: | |
Category: | MySQL Server: MyISAM storage engine | Severity: | S1 (Critical) |
Version: | 4.0.16 | OS: | Linux (RH 9, Apache 1.3.29) |
Assigned to: | Michael Widenius | CPU Architecture: | Any |
[12 Dec 2003 6:02]
Tom Zlos
[13 Dec 2003 19:40]
Michael Widenius
The following answer is from bug report #1758 There are a few separate, independent problems with indexes when one does a lot of deletes on a table - The cardinality of the index changes (not likely but possible) and MySQL uses the wrong index in the query. In this case one could try to update the cardinality with ANALYZE TABLE (faster than OPTIMIZE TABLE) or use IGNORE INDEX / USE INDEX in the query to get MySQL to use the right indexes. - The indexes gets 'unbalanced' and the range optimizer estimates wrongly the wrong number of matching keys for expressions like 'key_column op constant'. In this case one should update the index with OPTIMIZE TABLE or use IGNORE INDEX / USE INDEX. - The index files could be fragmented on disk, causing more seeks than are optimal, but I don't think this is the problem here. Neither of the above problems are frequent and only happens to some specific tables and specific usage. One common case where the index gets unbalanced is when you have an indexed timestamp columns and you insert a lot of new rows and delete a lot of old rows with an old timestamp. In this case the optimizer will estimate wrongly the number of rows for queries like WHERE timestamp_column BETWEEN date and data2 In most cases the estimate is still 'good enough' but we know of cases when the estimate is so wrong that MySQL will instead choose another index to solve the query. Fragmentation of indexes should not happen for just a single delete of one row. If this is the case then there is some unknown factor involved and we would need to get a test case to be able to find this out. To know what is happening in this particular case I would need the explain from tables before the delete is done (when the query was fast) and the explain after the delete was done (and the query is slow). You can the the information what exactly happened during a query by doing: mysql> FLUSH STATUS; mysql> SELECT ...; <A short version of the output from SELECT, including the time taken to run the query> mysql> SHOW STATUS; <output from SHOW STATUS> (The above assumes you are the only one using the system as the STATUS variables are global). The best way to know what is happening is of course if we could get a copy of the problem tables when the query is slow so that we can test this yourself. (Feel free to reset any columns that are not part of the query with NULL or ""). Upload the tables, with a description of the problem, to ftp://support.mysql.com/pub/mysql/secret. If you are unsure about the safety of your data, you can always take a support contract from MySQL AB as this will give you legal ground that your data is safe. NOTE: We resently found out that 4.0.16 has a bug (4.0.15 was ok) that it in some cases makes table scans when it doesn't have to. This will be fixed in 4.0.17 that will be out in a few days. Regards, Monty
[14 Dec 2003 9:55]
Tom Zlos
>To know what is happening in this particular case I would need the >explain from tables before the delete is done (when the query was fast) >and the explain after the delete was done (and the query is slow). I have tried my best to obtain this EXPLAIN, but as tables get locked it returns no result... The only thing which may lead to some conclusions is my slow queries log: # User@Host: user[user] @ www.foo.pl [192.168.10.11] # Query_time: 194 Lock_time: 169 Rows_sent: 5 Rows_examined: 20262 SELECT AVG(re.rating_value) as avgscore,r.*,r.date_added as date_review_added,i.*,v.* FROM rating as r, items as i, vendors as v, rating_entries as re WHERE (...) and please compare Rows_examined with this one # User@Host: user[user] @ www.foo.pl [192.168.10.11] # Query_time: 257 Lock_time: 201 Rows_sent: 5 Rows_examined: 94676 SELECT AVG(re.rating_value) as avgscore,r.*,r.date_added as date_review_added,i.*,v.* FROM rating as r, items as i, vendors as v, rating_entries as re WHERE (...) I am still observing mysql host with top command, these are my findings from performance point of view: - during ussual work free memory is approx. 400 MB, CPU load approx. 10% - when processes start to hang: :: RAM consumption jumps to 100%, :: CPU load approx. 50%, :: at the same time mysqld processes jump from 60-100MB to 400-500MB of memory :: tmp directory gets filled with approx. 4GB of temporary MYD and MYI files During hang I have tried to ANALYZE tables, but with no success. Only OPTIMIZE - while pushed through the process list, settles the problem. Mysql restart during the problem does not help, right after restarting again processes start to be hanged. Again, after restart only OPTIMIZE and manual killing of the hanged processes until OPTIMIZE TABLE gets unlocked are helping to solve the issue. Queries are using WHERE on logical condition and ORDER BY timestamp.
[14 Dec 2003 10:01]
Tom Zlos
TOP command during the hang produces this: ------------------------------------------ 19:13:53 up 2 days, 4:43, 1 user, load average: 38.14, 22.85, 10.72 182 processes: 132 sleeping, 50 running, 0 zombie, 0 stopped CPU states: 46.7% user 14.5% system 0.0% nice 0.0% iowait 38.6% idle Mem: 1022808k av, 1013364k used, 9444k free, 0k shrd, 154144k buff 627256k actv, 168424k in_d, 40636k in_c Swap: 1020088k av, 111620k used, 908468k free 446172k cache PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME CPU COMMAND 17075 mysql 16 0 440M 357M 1736 R 5.9 35.8 0:13 0 mysqld 17225 mysql 15 0 440M 357M 1736 S 3.9 35.8 0:10 0 mysqld 17249 mysql 16 0 440M 357M 1736 R 2.9 35.8 0:04 0 mysqld 17079 mysql 16 0 440M 357M 1736 R 2.7 35.8 0:26 0 mysqld 17237 mysql 16 0 440M 357M 1736 R 2.1 35.8 0:10 0 mysqld 16812 mysql 16 0 440M 357M 1736 R 1.9 35.8 0:45 0 mysqld 16817 mysql 15 0 440M 357M 1736 S 1.9 35.8 0:36 0 mysqld 17232 mysql 16 0 440M 357M 1736 R 1.9 35.8 0:06 0 mysqld 17235 mysql 15 0 440M 357M 1736 S 1.9 35.8 0:06 0 mysqld 16814 mysql 16 0 440M 357M 1736 R 1.7 35.8 0:57 0 mysqld 17233 mysql 15 0 440M 357M 1736 S 1.5 35.8 0:01 0 mysqld 17338 mysql 16 0 440M 357M 1736 R 1.5 35.8 0:00 0 mysqld 17240 mysql 15 0 440M 357M 1736 S 1.3 35.8 0:06 0 mysqld 17321 mysql 15 0 440M 357M 1736 S 1.3 35.8 0:00 0 mysqld 17334 mysql 15 0 440M 357M 1736 S 1.3 35.8 0:00 0 mysqld 16820 mysql 16 0 440M 357M 1736 R 1.1 35.8 0:33 0 mysqld 16822 mysql 16 0 440M 357M 1736 R 1.1 35.8 0:39 0 mysqld TOP command during the normal work produces this: -------------------------------------------------- 19:53:40 up 2 days, 5:23, 2 users, load average: 0.14, 0.13, 2.18 180 processes: 179 sleeping, 1 running, 0 zombie, 0 stopped CPU states: 0.0% user 100.0% system 0.0% nice 0.0% iowait 0.0% idle Mem: 1022808k av, 541028k used, 481780k free, 0k shrd, 162776k buff 320360k actv, 130080k in_d, 36852k in_c Swap: 1020088k av, 27472k used, 992616k free 217356k PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME CPU COMMAND 17711 root 16 0 1176 1176 808 R 99.9 0.1 0:00 0 top 1 root 15 0 104 68 52 S 0.0 0.0 0:03 0 init 2 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 keventd 3 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kapmd 4 root 34 19 0 0 0 SWN 0.0 0.0 0:02 0 ksoftirqd_CP 9 root 15 0 0 0 0 SW 0.0 0.0 0:02 0 bdflush 5 root 15 0 0 0 0 SW 0.0 0.0 0:06 0 kswapd 6 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kscand/DMA 7 root 16 0 0 0 0 SW 0.0 0.0 2:17 0 kscand/Norma 8 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kscand/HighM 10 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kupdated 11 root 24 0 0 0 0 SW 0.0 0.0 0:00 0 mdrecoveryd 17 root 25 0 0 0 0 SW 0.0 0.0 0:00 0 scsi_eh_0 18 root 25 0 0 0 0 SW 0.0 0.0 0:00 0 scsi_eh_1 21 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kjournald 78 root 25 0 0 0 0 SW 0.0 0.0 0:00 0 khubd 291 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kjournald 292 root 15 0 0 0 0 SW 0.0 0.0 0:22 0 kjournald 293 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kjournald 294 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kjournald 295 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kjournald 572 root 15 0 280 268 196 S 0.0 0.0 0:00 0 syslogd 576 root 15 0 56 4 0 S 0.0 0.0 0:00 0 klogd 585 root 15 0 364 224 140 S 0.0 0.0 0:00 0 sshd 596 root 24 0 148 4 0 S 0.0 0.0 0:00 0 xinetd 669 root 15 0 400 188 124 S 0.0 0.0 0:00 0 master 684 root 15 0 152 132 84 S 0.0 0.0 0:00 0 crond 696 root 21 0 56 4 0 S 0.0 0.0 0:00 0 mingetty 697 root 21 0 56 4 0 S 0.0 0.0 0:00 0 mingetty 698 root 21 0 56 4 0 S 0.0 0.0 0:00 0 mingetty 699 root 21 0 56 4 0 S 0.0 0.0 0:00 0 mingetty 700 root 21 0 56 4 0 S 0.0 0.0 0:00 0 mingetty 701 root 21 0 56 4 0 S 0.0 0.0 0:00 0 mingetty 16196 root 19 0 708 564 536 S 0.0 0.0 0:00 0 su 16197 root 15 0 1300 1292 940 S 0.0 0.1 0:00 0 bash 17378 root 25 0 1124 952 948 S 0.0 0.0 0:00 0 mysqld_safe 17403 mysql 15 0 102M 90M 1780 S 0.0 9.1 0:00 0 mysqld 17404 mysql 15 0 102M 90M 1780 S 0.0 9.1 0:00 0 mysqld 17405 mysql 20 0 102M 90M 1780 S 0.0 9.1 0:00 0 mysqld 17406 mysql 25 0 102M 90M 1780 S 0.0 9.1 0:00 0 mysqld 17407 mysql 25 0 102M 90M 1780 S 0.0 9.1 0:00 0 mysqld 17408 mysql 20 0 102M 90M 1780 S 0.0 9.1 0:00 0 mysqld 17409 mysql 24 0 102M 90M 1780 S 0.0 9.1 0:00 0 mysqld 17410 mysql 15 0 102M 90M 1780 S 0.0 9.1 0:00 0 mysqld 17411 mysql 24 0 102M 90M 1780 S 0.0 9.1 0:00 0 mysqld
[14 Dec 2003 10:45]
Tom Zlos
Here some files from my temp directory: „ Name „ Size „ MTime „ „ /.. „ UP--DIR„ „ „ #sql_43fb_0.MYD„ 118554K„ Dec 14 19:17„ „ #sql_43fb_0.MYI„ 1024„ Dec 14 19:15„ „ #sql_43fb_1.MYD„ 118554K„ Dec 14 19:17„ „ #sql_43fb_1.MYI„ 1024„ Dec 14 19:15„ „ #sql_43~_10.MYD„ 107529K„ Dec 14 19:17„ „ #sql_43~_10.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_11.MYD„ 100192K„ Dec 14 19:17„ „ #sql_43~_11.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_12.MYD„ 84877K„ Dec 14 19:17„ „ #sql_43~_12.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_13.MYD„ 95633K„ Dec 14 19:17„ „ #sql_43~_13.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_14.MYD„ 67684K„ Dec 14 19:17„ „ #sql_43~_14.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_15.MYD„ 108857K„ Dec 14 19:17„ „ #sql_43~_15.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_16.MYD„ 76829K„ Dec 14 19:17„ „ #sql_43~_16.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_17.MYD„ 59156K„ Dec 14 19:17„ „ #sql_43~_17.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_18.MYD„ 62723K„ Dec 14 19:17„ „ #sql_43~_18.MYI„ 1024„ Dec 14 19:16„ „ #sql_43fb_2.MYD„ 118554K„ Dec 14 19:16„ „ #sql_43fb_2.MYI„ 1024„ Dec 14 19:15„ „ #sql_43~_20.MYD„ 52171K„ Dec 14 19:17„ „ #sql_43~_20.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_23.MYD„ 11741K„ Dec 14 19:17„ „ #sql_43~_23.MYI„ 1024„ Dec 14 19:17„ „ #sql_43~_25.MYD„ 36821K„ Dec 14 19:17„ „ #sql_43~_25.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_26.MYD„ 41636K„ Dec 14 19:17„ „ #sql_43~_26.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_28.MYD„ 41697K„ Dec 14 19:17„ „ #sql_43~_28.MYI„ 1024„ Dec 14 19:16„ „ #sql_43fb_3.MYD„ 118554K„ Dec 14 19:17„ „ #sql_43fb_3.MYI„ 1024„ Dec 14 19:15„ „ #sql_43~_31.MYD„ 0„ Dec 14 19:16„ „ #sql_43~_31.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_32.MYD„ 33901K„ Dec 14 19:17„ „ #sql_43~_32.MYI„ 1024„ Dec 14 19:16„ „ #sql_43~_35.MYD„ 15362K„ Dec 14 19:17„ „ #sql_43~_35.MYI„ 1024„ Dec 14 19:17„ „ #sql_43~_37.MYD„ 11971K„ Dec 14 19:17„ „ #sql_43~_37.MYI„ 1024„ Dec 14 19:17„ „ #sql_43~_39.MYD„ 8368668„ Dec 14 19:17„ „ #sql_43~_39.MYI„ 1024„ Dec 14 19:17„ „ #sql_43fb_4.MYD„ 118554K„ Dec 14 19:17„ „ #sql_43fb_4.MYI„ 1024„ Dec 14 19:15„ Please correct me if I am wrong, but MYI files with 1024 size are just empty indexes, right?
[30 Jan 2004 5:45]
Michael Widenius
Don't understand what you mean with that you can't get an EXPLAIN becasue of table locks. EXPLAIN doesn't cause any new table locks compared to the SELECT that you are doing an EXPLAIN of. If you can do a SELECT you can do an EXPLAIN I am sorry, but it doesn't help to get a description of the problem you have as we know that MySQL in general works perfectly in situations likes yours. There must be something unique to your setup and until we know this, by having an exact, preferably repeatable example, it's very hard to help you solve this problem. If the situation is as you describe, it should be trivial to do a test case of this on another computer. Have you tried this ? MYI files with 1024 size are index files without index. (They just contain metadata for the .MYD file). Note that this public bug systems is only intended for bugs that we are able to trivially repeat. If you can create a repeatable bug of this, we will do our best to fix this to the next MySQL release. We can't however afford to spend time on finding a bug when we don't have enough information to repeat it as this could take any amount of time. Regards, Monty