Connecting Tech Pros Worldwide Help | Site Map

Index disabled after TRUNCATE

  #1  
Old May 24th, 2007, 05:13 PM
Newbie
 
Join Date: May 2007
Location: UK
Posts: 8
I have a series of tables in which the data can be refreshed from a file.

Before refreshing the data, some of the tables are cleared using either TRUNCATE or DELETE.

If TRUNCATE is used, any index which is not PRIMARY or UNIQUE appears to be disabled and is not updated when new data is inserted into the table.

Performing an OPTIMIZE reactivates the index.

If DELETE is used instead of TRUNCATE, this problem does not occur.

Does anyone know if this a fault, a feature, an option which can be changed?

MySQL version 4.1.20
  #2  
Old May 25th, 2007, 08:51 AM
pbmods's Avatar
Site Moderator
 
Join Date: Apr 2007
Location: Texas
Posts: 5,435
Provided Answers: 1

re: Index disabled after TRUNCATE


This probably has something to with the fact that TRUNCATE actually drops and recreates the table. It does not seem like it is supposed to do that, though, and I wasn't able to Google much about it. Try to see if you can reliably reproduce this behavior in a separate database.

You should also be able to re-enable the indexes by doing:

Expand|Select|Wrap|Line Numbers
  1. ALTER TABLE `tablename` ENABLE KEYS
  2.  
  #3  
Old May 25th, 2007, 02:16 PM
Motoma's Avatar
Moderator
 
Join Date: Jan 2007
Location: Maine, USA
Posts: 2,904

re: Index disabled after TRUNCATE


MySQL 4.1 has a lot of quirky 'features' in it. I would suggest upgrading to 5.
  #4  
Old May 25th, 2007, 09:16 PM
Newbie
 
Join Date: May 2007
Location: UK
Posts: 8

re: Index disabled after TRUNCATE


Quote:
Originally Posted by Motoma
MySQL 4.1 has a lot of quirky 'features' in it. I would suggest upgrading to 5.
Thanks for the advice, but not currently an option.

I'm running on a shared hosting system and because I was losing several indexes, my queries started performing badly (MySQL server overload), and my MySQL database was turned off - twice!

It was only after the second occurrence that I managed to get enough information to find out what was causing the problem.

Oh, and I have only just recently signed up with this host - the previous one suspended my account completely (e-mail, web, FTP, My SQL), again for MySQL server overload, presumably for the same reason.

I have a workround now, but you can see why I'm keen to understand the cause.
  #5  
Old May 26th, 2007, 01:48 PM
Motoma's Avatar
Moderator
 
Join Date: Jan 2007
Location: Maine, USA
Posts: 2,904

re: Index disabled after TRUNCATE


I have been in the same boat. It is really frustrating when you have to use an outdated version of MySQL, especially if you are stuck with one that does not support stored procedures or subqueries.
  #6  
Old May 26th, 2007, 05:34 PM
Newbie
 
Join Date: May 2007
Location: UK
Posts: 8

re: Index disabled after TRUNCATE


Quote:
Originally Posted by pbmods
This probably has something to with the fact that TRUNCATE actually drops and recreates the table. It does not seem like it is supposed to do that, though, and I wasn't able to Google much about it. Try to see if you can reliably reproduce this behavior in a separate database.

You should also be able to re-enable the indexes by doing:

Expand|Select|Wrap|Line Numbers
  1. ALTER TABLE `tablename` ENABLE KEYS
  2.  
After experimenting, it is not the TRUNCATE which disables the INDEXes - they are not activated from the time of the CREATE TABLE.

I created a copy of my table in another database.

There is a PRIMARY INDEX, a UNIQUE INDEX and 5 other INDEXes.

Running an OPTIMIZE TABLE or ANALYZE TABLE on the empty table returns 'Table is already up to date'.

INSERT INTO one or more rows and the PRIMARY INDEX and UNIQUE INDEX are updated - the other INDEXes are not.

ALTER TABLE `tablename` ENABLE KEYS has no effect .
Perhaps the INDEXES are not 'disabled', but they are certainly not active.

The only actions that seems to activate the INDEXes is OPTIMIZE TABLE or ANALYZE TABLE.

Once one of these is done, the INDEXes are maintained after any UPDATE, INSERT or DELETE.

TRUNCATE obviously drops and creates the table, and everything starts again.

Confused...
  #7  
Old May 26th, 2007, 06:50 PM
Motoma's Avatar
Moderator
 
Join Date: Jan 2007
Location: Maine, USA
Posts: 2,904

re: Index disabled after TRUNCATE


Could you build a simple test case that demonstrates this behavior? I would like to test this out, if you could write up the SQL statements starting from your create table, I would be very appreciative.
  #8  
Old May 29th, 2007, 01:04 PM
Newbie
 
Join Date: May 2007
Location: UK
Posts: 8

re: Index disabled after TRUNCATE


Quote:
Originally Posted by Motoma
Could you build a simple test case that demonstrates this behavior? I would like to test this out, if you could write up the SQL statements starting from your create table, I would be very appreciative.
I discarded the scripts and the data that I used to perform the test, but it was based on the table that had originally caused me the problem. There were 35 columns in this table, and some of it was sensitive data.

I will look at recreating a simple test case when I get chance, possibly later today.
  #9  
Old May 29th, 2007, 07:22 PM
Newbie
 
Join Date: May 2007
Location: UK
Posts: 8

re: Index disabled after TRUNCATE


Test case, simplified to the minimum below: -

Expand|Select|Wrap|Line Numbers
  1. DROP TABLE IF EXISTS Tester;
  2.  
  3. CREATE TABLE Tester
  4. (
  5.  ID INT(11) NOT NULL,
  6.  F1 VARCHAR(10) NOT NULL,
  7.  F2 VARCHAR(10) NOT NULL,
  8.  F3 VARCHAR(10) NOT NULL,
  9.  F4 VARCHAR(10) NOT NULL,
  10.  F5 DATETIME NOT NULL,
  11.  F6 TEXT NOT NULL,
  12.  PRIMARY KEY (ID),
  13.  UNIQUE I1 (F1, F2),
  14.  KEY I2 (F3, F4),
  15.  KEY I3 (F4),
  16.  KEY I4 (F1, F3, F4),
  17.  KEY I5 (F1, F4),
  18.  KEY I6 (F5)
  19. )
  20. TYPE = MYISAM;
Expand|Select|Wrap|Line Numbers
  1. SHOW INDEX FROM Tester;
Result: (PRIMARY and I1 cardinality 0; I2, I3, I4, I5, I6 cardinality NULL)

Expand|Select|Wrap|Line Numbers
  1. INSERT INTO Tester VALUES ('1', 'A1', 'A2', 'A3', 'A4', '2007-05-29', 'A5');
Expand|Select|Wrap|Line Numbers
  1. SHOW INDEX FROM Tester;
Result: (PRIMARY and I1 cardinality 1; I2, I3, I4, I5, I6 cardinality NULL)

Expand|Select|Wrap|Line Numbers
  1. OPTIMIZE TABLE Tester;
Expand|Select|Wrap|Line Numbers
  1. SHOW INDEX FROM Tester;
Result: (PRIMARY, I1, I2, I3, I4, I5, I6 all cardinality 1)
Note: ANALYZE TABLE Tester; has the same effect as OPTIMIZE TABLE Tester;

Expand|Select|Wrap|Line Numbers
  1. INSERT INTO Tester VALUES ('2', 'B1', 'B2', 'B3', 'B4', '2007-05-29', 'B5');
Expand|Select|Wrap|Line Numbers
  1. SHOW INDEX FROM Tester;
Result: (PRIMARY, I1, I2, I3, I4, I5, I6 all cardinality 2)
  #10  
Old May 29th, 2007, 07:57 PM
Motoma's Avatar
Moderator
 
Join Date: Jan 2007
Location: Maine, USA
Posts: 2,904

re: Index disabled after TRUNCATE


Thank you. I was able to reproduce this behavior in MySQL 4.0.16-nt.
One thing I noticed, however, this behavior is not present with the InnoDB database engine.
  #11  
Old May 29th, 2007, 08:11 PM
pbmods's Avatar
Site Moderator
 
Join Date: Apr 2007
Location: Texas
Posts: 5,435
Provided Answers: 1

re: Index disabled after TRUNCATE


Cardinality is an estimated value, which MySQL uses to determine whether to use an index (and which index to use) or do a full scan. Even after running ANALYZE (or OPTIMIZE) TABLE, the index cardinality might not be correct even for small tables. This has to do with how MySQL calculates cardinality (hint: it doesn't run through and count all the unique values).

http://dev.mysql.com/doc/refman/5.0/en/show-index.html
  #12  
Old May 29th, 2007, 08:12 PM
Motoma's Avatar
Moderator
 
Join Date: Jan 2007
Location: Maine, USA
Posts: 2,904

re: Index disabled after TRUNCATE


Try this out:

Expand|Select|Wrap|Line Numbers
  1. DROP TABLE IF EXISTS Tester;
  2. CREATE TABLE Tester
  3. (
  4. ID INT(11) NOT NULL AUTO_INCREMENT,
  5. K VARCHAR(10),
  6. U VARCHAR(1),
  7. PRIMARY KEY(ID),
  8. UNIQUE I1 (U),
  9. KEY K1 (K)
  10. )
  11. TYPE = MyISAM;
  12.  
  13. INSERT INTO Tester (K, U) VALUES ('2', '3');
  14. INSERT INTO Tester (K, U) VALUES ('2', '3');
  15. SHOW INDEX FROM Tester;
  16.  
I am not allowed to insert the second row, which leads me to believe the key is being enforced. I would be interested in hearing your ideas on this matter.
  #13  
Old May 30th, 2007, 07:11 AM
Newbie
 
Join Date: May 2007
Location: UK
Posts: 8

re: Index disabled after TRUNCATE


Quote:
Originally Posted by pbmods
Cardinality is an estimated value, which MySQL uses to determine whether to use an index (and which index to use) or do a full scan. Even after running ANALYZE (or OPTIMIZE) TABLE, the index cardinality might not be correct even for small tables. This has to do with how MySQL calculates cardinality (hint: it doesn't run through and count all the unique values).

http://dev.mysql.com/doc/refman/5.0/en/show-index.html
My test case used only 2 rows, but in my live environment, the same results were there even after inserting more than 2,500 rows.

If MySQL determines its SQL execution plan based on what it knows about index cardinality and it sees NULL, then whether the index is present or not, this would cause the problem I was experiencing. Not too much of an overhead when processing a single table, but my code included multiple tables including a self join on this 2,500 row table.

The documentation for SHOW INDEX implies that ANALYZE TABLE (and I believe also OPTIMIZE TABLE) initially populates the cardinality of an index, but it also seems to be maintained thereafter (accurately in my experience) after every insert, update, delete.

My tables in this database are rebuilt regularly, and the fact that an ANALYZE is needed to activate the index is probably all I need to know to make sure I don't fall into the same trap again.
  #14  
Old May 30th, 2007, 07:56 AM
Newbie
 
Join Date: May 2007
Location: UK
Posts: 8

re: Index disabled after TRUNCATE


Quote:
Originally Posted by Motoma
Try this out:

Expand|Select|Wrap|Line Numbers
  1. DROP TABLE IF EXISTS Tester;
  2. CREATE TABLE Tester
  3. (
  4. ID INT(11) NOT NULL AUTO_INCREMENT,
  5. K VARCHAR(10),
  6. U VARCHAR(1),
  7. PRIMARY KEY(ID),
  8. UNIQUE I1 (U),
  9. KEY K1 (K)
  10. )
  11. TYPE = MyISAM;
  12.  
  13. INSERT INTO Tester (K, U) VALUES ('2', '3');
  14. INSERT INTO Tester (K, U) VALUES ('2', '3');
  15. SHOW INDEX FROM Tester;
  16.  
I am not allowed to insert the second row, which leads me to believe the key is being enforced. I would be interested in hearing your ideas on this matter.
Yes, I agree, the uniqueness of index I1 is enforced, but the cardinality still shows as null. This implies to me that the index is present, but it's no use unless My SQL knows about it when it determines the best execution plan.
  #15  
Old May 30th, 2007, 05:28 PM
Motoma's Avatar
Moderator
 
Join Date: Jan 2007
Location: Maine, USA
Posts: 2,904

re: Index disabled after TRUNCATE


Quote:
Originally Posted by Sandham
Yes, I agree, the uniqueness of index I1 is enforced, but the cardinality still shows as null. This implies to me that the index is present, but it's no use unless My SQL knows about it when it determines the best execution plan.
This may be the case; have you tried running an EXPLAIN to see if the index is being used in that circumstance?
  #16  
Old May 30th, 2007, 11:28 PM
Newbie
 
Join Date: May 2007
Location: UK
Posts: 8

re: Index disabled after TRUNCATE


Quote:
Originally Posted by Motoma
This may be the case; have you tried running an EXPLAIN to see if the index is being used in that circumstance?
No, I hadn't run an EXPLAIN on the query, but I have now, using phpMyAdmin.

Firstly, I ran an EXPLAIN on the query with the tables optimized.
Then, I reloaded my data (which performs a TRUNCATE first), and ran the EXPLAIN again.
(Followed very quickly by optimizing all the tables again!)

I was not familiar with the output of EXPLAIN for MySQL, but having read the documentation, my interpretation is as follows.

In both cases, the non-unique keys that I would expect to be used are listed under 'possible_keys'.

In an optimized state, for each reference to the table, one of the non-unique keys is listed under 'key' - the non-unique indexes would be used.

In a non-optimized state, for each reference to the table, only the unique index is shown under 'key' - the non-unique indexes would not be used.
Reply


Similar Threads
Thread Thread Starter Forum Replies Last Post
comp.lang.c Answers to Frequently Asked Questions (FAQ List) Steve Summit answers 0 November 14th, 2005 04:15 AM
comp.lang.c Answers to Frequently Asked Questions (FAQ List) Steve Summit answers 0 November 13th, 2005 11:37 PM
comp.lang.c Answers to Frequently Asked Questions (FAQ List) Steve Summit answers 0 November 13th, 2005 09:56 PM
comp.lang.c Answers to Frequently Asked Questions (FAQ List) Steve Summit answers 0 November 13th, 2005 03:15 AM