Есть ли лучший индекс для ускорения этого запроса? - PullRequest
3 голосов
/ 03 сентября 2010

Следующий запрос использует временную и файловую сортировку. Я хотел бы избежать этого, если это возможно.

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;

EXPLAIN говорит:

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

Таблицы выглядят так:

Библиотека

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;

последовательность

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;

Могу ли я сделать какие-либо изменения, чтобы ускорить выполнение запроса? Если нет, то когда (для веб-приложения) стоит поместить результаты запроса, подобного приведенному выше, в таблицу MEMORY?

1 Ответ

1 голос
/ 04 сентября 2010

Первая стратегия: сделайте так, чтобы mySQL быстрее находил записи, которые вы хотите обобщить.

У вас уже есть индекс sequence.is_contig. Вы можете попробовать проиндексировать библиотеки .foreign_seqs. Не знаю, поможет ли это, но стоит попробовать.

Вторая стратегия: посмотрите, сможете ли вы выполнить сортировку в памяти, а не в файле. Попробуйте увеличить параметр sort_buffer_size. Это будет потреблять оперативную память на вашем сервере, но для этого нужна оперативная память.

Третья стратегия: ЕСЛИ ваше приложение должно много выполнять этот запрос, но обновляет базовые данные лишь немного, примите ваше собственное предложение и создайте сводную таблицу. Возможно, используйте СОБЫТИЕ, чтобы переделать сводную таблицу, и запускайте ее каждые несколько минут. Если вы собираетесь следовать этой стратегии, начните с создания представления с этой таблицей, и ваше приложение получит информацию из представления. Затем включите работу сводной таблицы, отбросьте представление и присвойте итоговой таблице то же имя, что и представление. Таким образом, работа модели данных и разработка приложения могут выполняться независимо друг от друга.

Последнее предложение: если это действительно медленно меняющиеся сводные данные, переключитесь на myISAM. Это немного быстрее для такого рода обработки данных.

...