MySQL, table requires to run "optimize" command too often - mysql

I have a table that is growing about 200MB/hour.
If I run the optimize command on it, the size is reduced to 2MB and start growing again.
The table is a WordPress installation with very few visits (~100/day).
I was wondering if there is something wrong with this table, this is the table schema:
CREATE TABLE `wpii_options` (
`option_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`option_name` varchar(191) NOT NULL DEFAULT '',
`option_value` longtext NOT NULL,
`autoload` varchar(20) NOT NULL DEFAULT 'yes',
PRIMARY KEY (`option_id`),
UNIQUE KEY `option_name` (`option_name`)
) ENGINE=InnoDB AUTO_INCREMENT=16525 DEFAULT CHARSET=utf8
MySQL version 5.5.49-cll-lve

If unnecessary, try to reduce to:
bigint(20) -> int(20)
longtext -> text

Related

MySQL Workbench wont make constraint when parent table has Generated Virtual columns

SETUP
MySQL Workbench (ver 6.3.9)
MySQL 5.7.21
My setup is simple.. I have 2 tables:
CREATE TABLE `UserDevices` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`UserID` int(11) DEFAULT NULL,
`UUID` binary(16) DEFAULT NULL,
`DeviceName` varchar(45) DEFAULT NULL,
`DeviceType` tinyint(3) NOT NULL DEFAULT '1',
`CreatedDate` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`TimeStamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE `UserInfo` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`UUID` binary(16) DEFAULT NULL,
`UUIDText` varchar(40) GENERATED ALWAYS AS (insert(insert(insert(insert(hex(`UUID`),9,0,'-'),14,0,'-'),19,0,'-'),24,0,'-')) VIRTUAL,
`FirstName` varchar(45) DEFAULT NULL,
`LastName` varchar(45) DEFAULT NULL,
`FullName` varchar(90) GENERATED ALWAYS AS (concat(`FirstName`,' ',`LastName`)) VIRTUAL,
`Email` varchar(120) DEFAULT NULL,
`Status` tinyint(3) DEFAULT '0',
`AccountType` tinyint(3) DEFAULT '1',
`CreatedDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`TimeStamp` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
PROBLEM
When working inside Workbench I'm simply trying to Make a Foreign key constraint in table "UserDevices" on Column "UserID" Pointed at Table "UserInfo" Column "ID". When selecting "UserInfo" as the Referenced Table. I can not put a check next to UserID.. Also no columns show up in the drop down list under Referenced Column..
QUESTION
I understand there are a number of reasons this scenario would happen. But I'm not seeing Any data type mismatch or such that would explain this. What is making it so I can't select UserID.ID?
P.S. Setting up another table named "DeviceMeasurements" with a Column "DeviceID" I'm completely successful at setting up the constraint exactly as expected.
UPDATE
On a hunch since this is my first time playing around with Generated Virtual Columns. I went into the table and removed columns "UUIDText" and "FullName". NOW I can build my constraints as desired. But my question stands. Why can't I build constraint with the tables built as above!?
UPDATE 2
This has been confirmed as a bug in WorkBench. Manually adding the constraint via SQL code is a valid work around currently. Please see accepted answer.
Can confirm, this is a bug in WB. Have raised it with MySQL dev team.
Bug link

Importing WordPress Database - #1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key

I'm trying to move a WordPress database from Plesk to cPanel using phpMyAdmin but I get the following error when importing:
SQL query:
Table structure for table `wp_commentmeta`
CREATE TABLE IF NOT EXISTS `wp_commentmeta` (
`meta_id` BIGINT( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT ,
`comment_id` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0',
`meta_key` VARCHAR( 255 ) DEFAULT NULL ,
`meta_value` LONGTEXT
) ENGINE = MYISAM AUTO_INCREMENT =236 DEFAULT CHARSET = utf8;
MySQL said: Documentation
#1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key
I exported the database using the quick option as I normally do then just did a normal import.
The relevant part of the sql export is:
--
-- Table structure for table `wp_commentmeta`
--
CREATE TABLE IF NOT EXISTS `wp_commentmeta` (
`meta_id` bigint(20) unsigned NOT NULL auto_increment,
`comment_id` bigint(20) unsigned NOT NULL default '0',
`meta_key` varchar(255) default NULL,
`meta_value` longtext
) ENGINE=MyISAM AUTO_INCREMENT=236 DEFAULT CHARSET=utf8;
So I tried a solution mentioned on Google
CREATE TABLE IF NOT EXISTS `wp_commentmeta` (
`meta_id` bigint(20) unsigned NOT NULL PRIMARY KEY auto_increment,
`comment_id` bigint(20) unsigned NOT NULL default '0',
`meta_key` varchar(255) default NULL,
`meta_value` longtext
) ENGINE=MyISAM AUTO_INCREMENT=236 DEFAULT CHARSET=utf8;
And this time I got this error:
SQL query:
CREATE TABLE IF NOT EXISTS `wp_comments` (
`comment_ID` BIGINT( 20 ) UNSIGNED NOT NULL AUTO_INCREMENT ,
`comment_post_ID` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0',
`comment_author` TINYTEXT NOT NULL ,
`comment_author_email` VARCHAR( 100 ) NOT NULL DEFAULT '',
`comment_author_url` VARCHAR( 200 ) NOT NULL DEFAULT '',
`comment_author_IP` VARCHAR( 100 ) NOT NULL DEFAULT '',
`comment_date` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`comment_date_gmt` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`comment_content` TEXT NOT NULL ,
`comment_karma` INT( 11 ) NOT NULL DEFAULT '0',
`comment_approved` VARCHAR( 20 ) NOT NULL DEFAULT '1',
`comment_agent` VARCHAR( 255 ) NOT NULL DEFAULT '',
`comment_type` VARCHAR( 20 ) NOT NULL DEFAULT '',
`comment_parent` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0',
`user_id` BIGINT( 20 ) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE = MYISAM AUTO_INCREMENT =226 DEFAULT CHARSET = utf8;
MySQL said: Documentation
#1075 - Incorrect table definition; there can be only one auto column and it must be defined as a key
The CREATE section for wp_comments is as follows.
DROP TABLE IF EXISTS `wp_comments`;
CREATE TABLE IF NOT EXISTS `wp_comments` (
`comment_ID` bigint(20) unsigned NOT NULL auto_increment,
`comment_post_ID` bigint(20) unsigned NOT NULL default '0',
`comment_author` tinytext NOT NULL,
`comment_author_email` varchar(100) NOT NULL default '',
`comment_author_url` varchar(200) NOT NULL default '',
`comment_author_IP` varchar(100) NOT NULL default '',
`comment_date` datetime NOT NULL default '0000-00-00 00:00:00',
`comment_date_gmt` datetime NOT NULL default '0000-00-00 00:00:00',
`comment_content` text NOT NULL,
`comment_karma` int(11) NOT NULL default '0',
`comment_approved` varchar(20) NOT NULL default '1',
`comment_agent` varchar(255) NOT NULL default '',
`comment_type` varchar(20) NOT NULL default '',
`comment_parent` bigint(20) unsigned NOT NULL default '0',
`user_id` bigint(20) unsigned NOT NULL default '0'
) ENGINE=MyISAM AUTO_INCREMENT=226 DEFAULT CHARSET=utf8;
At the bottom of the dump is the following auto_increment information.
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `wp_commentmeta`
--
ALTER TABLE `wp_commentmeta`
AUTO_INCREMENT=236;
--
-- AUTO_INCREMENT for table `wp_comments`
--
ALTER TABLE `wp_comments`
AUTO_INCREMENT=226;
--
-- AUTO_INCREMENT for table `wp_event_list`
--
ALTER TABLE `wp_event_list`
AUTO_INCREMENT=9;
--
-- AUTO_INCREMENT for table `wp_layerslider`
--
ALTER TABLE `wp_layerslider`
AUTO_INCREMENT=6;
--
-- AUTO_INCREMENT for table `wp_options`
--
ALTER TABLE `wp_options`
AUTO_INCREMENT=497473;
--
-- AUTO_INCREMENT for table `wp_postmeta`
--
ALTER TABLE `wp_postmeta`
AUTO_INCREMENT=18312;
--
-- AUTO_INCREMENT for table `wp_posts`
--
ALTER TABLE `wp_posts`
AUTO_INCREMENT=2083;
--
-- AUTO_INCREMENT for table `wp_terms`
--
ALTER TABLE `wp_terms`
AUTO_INCREMENT=136;
--
-- AUTO_INCREMENT for table `wp_term_taxonomy`
--
ALTER TABLE `wp_term_taxonomy`
AUTO_INCREMENT=137;
--
-- AUTO_INCREMENT for table `wp_usermeta`
--
ALTER TABLE `wp_usermeta`
AUTO_INCREMENT=1527;
--
-- AUTO_INCREMENT for table `wp_users`
--
ALTER TABLE `wp_users`
AUTO_INCREMENT=43;
--
-- AUTO_INCREMENT for table `wp_woocommerce_attribute_taxonomies`
--
ALTER TABLE `wp_woocommerce_attribute_taxonomies`
AUTO_INCREMENT=5;
--
-- AUTO_INCREMENT for table `wp_woocommerce_order_itemmeta`
--
ALTER TABLE `wp_woocommerce_order_itemmeta`
AUTO_INCREMENT=1869;
--
-- AUTO_INCREMENT for table `wp_woocommerce_order_items`
--
ALTER TABLE `wp_woocommerce_order_items`
AUTO_INCREMENT=294;
--
-- AUTO_INCREMENT for table `wp_woocommerce_tax_rates`
--
ALTER TABLE `wp_woocommerce_tax_rates`
AUTO_INCREMENT=4;
--
-- AUTO_INCREMENT for table `wp_woocommerce_termmeta`
--
ALTER TABLE `wp_woocommerce_termmeta`
AUTO_INCREMENT=116;
And this is where I'm really stuck as I've rapidly and suddenly reached the limit of my knowledge and don't want to make matters worse. I'm used to seeing the info in the alter table section within the create and don't know id I should be copying it into the create sections or what.
Can someone please provide some hints as to why this is occurring.
Thanks.
For each Wordpress table, add its key in this way (see the penultimate line):
CREATE TABLE IF NOT EXISTS `wp_commentmeta` (
`meta_id` bigint(20) unsigned NOT NULL auto_increment,
`comment_id` bigint(20) unsigned NOT NULL default '0',
`meta_key` varchar(255) default NULL,
`meta_value` longtext,
key (meta_id) -- add this line (remember to add the comma in the previous line)
) ENGINE=MyISAM AUTO_INCREMENT=236 DEFAULT CHARSET=utf8;
Wordpress tables:
wp_commentmeta
wp_comments
wp_links
wp_options
wp_postmeta
wp_posts
wp_terms
wp_term_relationships
wp_term_taxonomy
wp_usermeta
wp_users
Possible that you are using two different versions of phpmyadmin, one in plesk, the other one in your cpanel system?
You could try 'Adminer', which is a powerful phpmyadmin alternative and it is based on only one single file!
Download it from here: http://www.adminer.org/en/
Copy adminer.php to the server where you want to get the export from and to the one where you want to import the sql data.
Go to your website/adminer.php and login to your db with the credentials you have. The Export and import is similar to phpmyadmin but the advantage is that you are using one common version of the adminer software which makes sure that import and export is gonna be run fine.
I have the same problem when I export from another phpMyAdmin, the file mysql export does not include primary key in there, then when exporting I choosed method "Custom - display all possible options", then I checked "IF NOT EXISTS (less efficient as indexes will be generated during table creation)". And then the exported file included primary key in the file. And my problem is solved. I hope this help you.
This problem is documented by phpMyAdmin (PMA) and "fixed" by essentially saying that you can't use the current version with MySQL 5.0.
http://sourceforge.net/p/phpmyadmin/bugs/4437/
http://sourceforge.net/p/phpmyadmin/bugs/4261/
Table export with auto_increment, primary key creates invalid statements > Problems due to missing enforcement of the minimum supported MySQL version
Found out my server is running PMA 4.3 with MYSQL 5.0.95 whereas my local is MYSQL 5.5. I don't know why this is a problem now, as older PMA would import/export beautifully as mysqldump, I guess they changed and simplified the syntax for performances reasons which is legit.
If you're like me, you exported your tables from MySQL 5.5 (hosting server) and tried to import into MySQL 5.6 (XAMPP on Mac) and you got the dreaded 1075 error. After searching on the Internet for hours you found out it has something to do with the Auto-increment and Primary key. Not being a database programmer, this information (provided in links by liquified, above) does not help solve the problem as you're basically told: "Hey, don't do that". Well mr. PMA bug, it's already done, so how do I fix it?
Here's what worked for me:
The SQL you exported has a bunch of statements near the bottom to "ALTER" all the tables you created at top. All you need to do is copy into the CREATE statement above.
So, at the bottom, your ALTER wp_commentmeta looks like this:
ALTER TABLE `wp_commentmeta`
ADD PRIMARY KEY (`meta_id`),
ADD KEY `comment_id` (`comment_id`),
ADD KEY `meta_key` (`meta_key`);
And at the top, the CREATE looks like this:
CREATE TABLE IF NOT EXISTS `wp_commentmeta` (
`meta_id` bigint(20) unsigned NOT NULL auto_increment,
`comment_id` bigint(20) unsigned NOT NULL default '0',
`meta_key` varchar(255) default NULL,
`meta_value` longtext
) TYPE=MyISAM AUTO_INCREMENT=67;
The solution is to remove the ALTER at bottom and put those statements into the CREATE, like this (adding the comma after the 'longtext'):
CREATE TABLE IF NOT EXISTS `wp_commentmeta` (
`meta_id` bigint(20) unsigned NOT NULL auto_increment,
`comment_id` bigint(20) unsigned NOT NULL default '0',
`meta_key` varchar(255) default NULL,
`meta_value` longtext,
PRIMARY KEY (`meta_id`),
KEY `comment_id` (`comment_id`),
KEY `meta_key` (`meta_key`)
) TYPE=MyISAM AUTO_INCREMENT=67;
Now, if you use this, you'll get a 1064 error for bad syntax. Can a guy get a break? You still need to change the MyISAM stuff for this new version:
TYPE=MyISAM AUTO_INCREMENT=67;
change to
ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=67;
In the end your final CREATE declaration will look like this and you won't need any ALTER table statements at the bottom of your SQL:
CREATE TABLE IF NOT EXISTS `wp_commentmeta` (
`meta_id` bigint(20) unsigned NOT NULL auto_increment,
`comment_id` bigint(20) unsigned NOT NULL default '0',
`meta_key` varchar(255) default NULL,
`meta_value` longtext,
PRIMARY KEY (`meta_id`),
KEY `comment_id` (`comment_id`),
KEY `meta_key` (`meta_key`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=50 ;
Yes, you have to manually edit your SQL if you plan on importing it into the new DB. If you have a lot of tables and/or websites affected by this 'bug', it will take some time, so grab a coffee, whatever works, and fix it and move on with your life.
Now, if you still get errors, check your syntax, make sure to remove 'ADD' when you copy from the ALTER table. Remove ';' and use commas correctly. If you managed to import part of the DB, a few tables, but got snagged on syntax, DUMP all tables and try your import again once you've made the fix. I encountered a 1062: duplicate primary key because I managed to import some tables and others failed. When I tried to import again, the primary key was already set for the table.
All this headache because of performance 'enhancements' in new PMA/MySQL. Humbug!

Why do i HAVE to optimize tables?

I have a pretty big table with contains about 3 million records.
When running a very simple query, joining this table on a few others (all with indexes and/or primary keys), the query will take about 25 seconds to complete!
The value of "Handler_read_next" is about 7 million!
Number of requests to read the next row in key order, incremented if you are querying an index column with a range constraint or if you are doing an index scan.
This problem have only started since this table began to grow big.
Now if I do an "optimize tables" on this table, the query will run in about 0.02 seconds and "Handler_read_next" will have a value of about 1500.
How can the difference be so extreme, and do I really have to setup a scheduled query, optimizing this table once a week or so? Even so, I would like to know the meaning behind this and why mysql behaves like this. Sure, rows are deleted and updated pretty much in this table, but should it get so badly fragmented in only one week that the query goes from 0.02 sec to 25 sec?
Edit: After request, here comes the query in question:
SELECT *
FROM budget_expenses
JOIN budget_categories
ON budget_categories.BudgetAreaId = budget_expenses.BudgetAreaId
AND budget_categories.BudgetCategoryId = budget_expenses.BudgetCategoryId
LEFT JOIN budget_types
ON budget_types.BudgetAreaId = budget_expenses.BudgetAreaId
AND budget_types.BudgetCategoryId = budget_expenses.BudgetCategoryId
AND budget_types.BudgetTypeId = budget_expenses.BudgetTypeId
WHERE budget_expenses.BudgetId = 1
AND budget_expenses.ExpenseDate >= '2012-11-25'
AND budget_expenses.ExpenseDate <= '2012-12-24'
AND budget_expenses.BudgetAreaId = 2
ORDER BY budget_expenses.ExpenseDate DESC,
budget_expenses.ExpenseTime IS NULL ASC,
budget_expenses.ExpenseTime DESC
(BudgetAreaId, BudgetCategoryId) is the primary key in budget_categories and (BudgetAreaId, BudgetCategoryId, BudgetTypeId) is the primary key in budget_types. In budget_expenses these 3 keys are indexes and also ExpenseDate has an index. This query returns about 20 rows.
Show create table:
CREATE TABLE `budget_areas` (
`BudgetAreaId` int(11) NOT NULL,
`Name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`BudgetAreaId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `budget_categories` (
`BudgetAreaId` int(11) NOT NULL,
`BudgetCategoryId` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(255) DEFAULT NULL,
`SortOrder` int(11) DEFAULT NULL,
PRIMARY KEY (`BudgetAreaId`,`BudgetCategoryId`),
KEY `BudgetAreaId` (`BudgetAreaId`,`BudgetCategoryId`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
CREATE TABLE `budget_types` (
`BudgetAreaId` int(11) NOT NULL,
`BudgetCategoryId` int(11) NOT NULL,
`BudgetTypeId` int(11) NOT NULL,
`Name` varchar(255) DEFAULT NULL,
`SortId` int(11) DEFAULT NULL,
PRIMARY KEY (`BudgetAreaId`,`BudgetCategoryId`,`BudgetTypeId`),
KEY `BudgetAreaId` (`BudgetAreaId`,`BudgetCategoryId`,`BudgetTypeId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `budget_expenses` (
`ExpenseId` int(11) NOT NULL AUTO_INCREMENT,
`BudgetId` int(11) NOT NULL,
`TempId` int(11) DEFAULT NULL,
`BudgetAreaId` int(11) DEFAULT NULL,
`BudgetCategoryId` int(11) DEFAULT NULL,
`BudgetTypeId` int(11) DEFAULT NULL,
`Company` varchar(255) DEFAULT NULL,
`ImportCompany` varchar(255) DEFAULT NULL,
`Sum` double(50,2) DEFAULT NULL,
`ExpenseDate` date DEFAULT NULL,
`ExpenseTime` time DEFAULT NULL,
`Inserted` datetime DEFAULT NULL,
`Changed` datetime DEFAULT NULL,
`InsertType` int(1) DEFAULT NULL,
`AccountId` int(11) DEFAULT NULL,
`BankCardId` int(11) DEFAULT NULL,
PRIMARY KEY (`ExpenseId`),
KEY `BudgetId` (`BudgetId`),
KEY `AccountId` (`AccountId`),
KEY `Company` (`Company`) USING BTREE,
KEY `ExpenseDate` (`ExpenseDate`),
KEY `BudgetAreaId` (`BudgetAreaId`),
KEY `BudgetCategoryId` (`BudgetCategoryId`),
KEY `BudgetTypeId` (`BudgetTypeId`),
CONSTRAINT `budget_expenses_ibfk_1` FOREIGN KEY (`BudgetId`) REFERENCES `budgets` (`BudgetId`)
) ENGINE=InnoDB AUTO_INCREMENT=3604462 DEFAULT CHARSET=latin1
After I copy pasted this I changed from MyIsam to Innodb on the budget_categories table.
Edit: The change from myisam to innodb didn't make any difference. The query is now very slow, just 12 hours after i optimized the budget_expenses table!
Here is the explain for the query which now takes about 9 seconds:
http://jsfiddle.net/dmVPY/1/
Ahhh MyISAM....
Try changing the table type (aka 'storage engine') to InnoDB instead.
If you do this, make sure innodb_buffer_pool_size in your my.cnf is a sensible value - the default is too small.

How do fields not selected for in a MySQL query affect query speed for the fields I am selecting on?

This is a theoretical question based on an application I have. I am wondering if there is some technical insight to be gained beyond just speed tests on my system.
I have the following two tables:
CREATE TABLE `files` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`url` varchar(255) NOT NULL DEFAULT '',
`processed` tinyint(1) unsigned NOT NULL DEFAULT '0',
`last_processed` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `url` (`url`),
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
and...
CREATE TABLE `file_metas` (
`file_id` int(10) unsigned NOT NULL,
`title` varchar(255) NOT NULL DEFAULT '',
`description` varchar(1000) NOT NULL DEFAULT '',
`keywords` varchar(1000) NOT NULL DEFAULT '',
PRIMARY KEY (`file_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
The file_metas data is long text strings about each file from the files table. Each file only has one entry in the file_metas table so these two tables could be combined.
I'm wondering what affect adding the long text fields to the files table will have on the performance of select statements done on the files table when I'm not selecting for title, description, or keywords. I'm curious about the technical details. Does simply having the text fields in the table slow queries not involving those fields? How does this work in general with MySQL MyISAM tables? Is there any good reason to keep the file_metas data in a separate table?

Is there a better index to speed up this query?

The following query is using temporary and filesort. I'd like to avoid that if possible.
SELECT lib_name, description, count(seq_id), floor(avg(size))
FROM libraries l JOIN sequence s ON (l.lib_id=s.lib_id)
WHERE s.is_contig=0 and foreign_seqs=0 GROUP BY lib_name;
The EXPLAIN says:
id,select_type,table,type,possible_keys,key,key_len,ref,rows,Extra
1,SIMPLE,s,ref,libseq,contigs,contigs,4,const,28447,Using temporary; Using filesort
1,SIMPLE,l,eq_ref,PRIMARY,PRIMARY,4,s.lib_id,1,Using where
The tables look like this:
libraries
CREATE TABLE `libraries` (
`lib_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`lib_name` varchar(30) NOT NULL,
`method_id` int(10) unsigned DEFAULT NULL,
`lib_efficiency` decimal(4,2) unsigned DEFAULT NULL,
`insert_avg` decimal(5,2) DEFAULT NULL,
`insert_high` decimal(5,2) DEFAULT NULL,
`insert_low` decimal(5,2) DEFAULT NULL,
`amtvector` decimal(4,2) unsigned DEFAULT NULL,
`description` text,
`foreign_seqs` tinyint(1) NOT NULL DEFAULT '0' COMMENT '1 means the sequences in this library are not ours',
PRIMARY KEY (`lib_id`),
UNIQUE KEY `lib_name` (`lib_name`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;
sequence
CREATE TABLE `sequence` (
`seq_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`seq_name` varchar(40) NOT NULL DEFAULT '',
`lib_id` int(10) unsigned DEFAULT NULL,
`size` int(10) unsigned DEFAULT NULL,
`add_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`sequencing_date` date DEFAULT '0000-00-00',
`comment` text DEFAULT NULL,
`is_contig` int(10) unsigned NOT NULL DEFAULT '0',
`fasta_seq` longtext,
`primer` varchar(15) DEFAULT NULL,
`gc_count` int(10) DEFAULT NULL,
PRIMARY KEY (`seq_id`),
UNIQUE KEY `seq_name` (`seq_name`),
UNIQUE KEY `libseq` (`lib_id`,`seq_id`),
KEY `primer` (`primer`),
KEY `sgitnoc` (`seq_name`,`is_contig`),
KEY `contigs` (`is_contig`,`seq_name`) USING BTREE,
CONSTRAINT `FK_sequence_1` FOREIGN KEY (`lib_id`) REFERENCES `libraries` (`lib_id`)
) ENGINE=InnoDB AUTO_INCREMENT=61508 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC;
Are there any changes I can do to make the query go faster? If not, when (for a web application) is it worth putting the results of a query like the above into a MEMORY table?
First strategy: make it faster for mySQL to locate the records you want summarized.
You've already got an index on sequence.is_contig. You might try indexing on libraries.foreign_seqs. I don't know if that will help, but it's worth a try.
Second strategy: see if you can get your sort to run in memory, rather than in a file. Try making the sort_buffer_size parameter bigger. This will consume RAM on your server, but that's what RAM is for.
Third strategy: IF your application needs to do this query a lot but updates the underlying data only a little, take your own suggestion and create a summary table. Perhaps use an EVENT to remake the summary table., and run it once every few minutes. If you're going to follow that strategy, start by creating a view with this table in it and have your app retrieve information from the view. Then get the summary table stuff working, drop the view, and give the summary table the same name as the view. That way your data model work and your application design work can proceed independently of each other.
Final suggestion: If this is truly slowly-changing summary data, switch to myISAM. It's a little faster for this kind of data wrangling.