2012-06-15 3 views
4

У меня очень большая таблица из более чем 9 миллионов строк, и в моем программном обеспечении мне нужно быстро делать запросы на нее в цикле. Проблема в том, что запросы занимают почти 4 секунды. Вот один из запросов (все они похожи в том, что все они имеют то же самое ИНЕКЕ, что замедляет их вниз:.MySQL Как я могу ускорить этот запрос SELECT?

SELECT MIN(id) 
FROM `04c1Tg0M` 
WHERE `tried` = 0; 

Я использую проверенную колонку как логическое значение 1 или 0. Здесь РАЗЪЯСНЯЕМ из этого запроса:

--------+--------------------------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra     | 
+----+-------------+----------+-------+---------------+------+---------+------+---------+--------------------------+ 
| 1 | SIMPLE  | 04c1Tg0M | index | NULL   | pdex | 158  | NULL | 9275107 | Using where; Using index | 
+----+-------------+----------+-------+---------------+------+---------+------+---------+--------------------------+ 

Вот структура таблицы:

CREATE TABLE `04c1Tg0M` (
    `id` int(20) NOT NULL AUTO_INCREMENT, 
    `username` varchar(50) NOT NULL, 
    `tried` tinyint(1) DEFAULT '0', 
    PRIMARY KEY (`id`), 
    KEY `pdex` (`username`,`id`,`tried`) 
) ENGINE=MyISAM AUTO_INCREMENT=9275108 DEFAULT CHARSET=utf8 

Здесь выход шоу Indes:

| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| 04c1Tg0M |   0 | PRIMARY |   1 | id   | A   |  9275107 |  NULL | NULL |  | BTREE  |   | 
| 04c1Tg0M |   1 | pdex  |   1 | username | A   |  9275107 |  NULL | NULL |  | BTREE  |   | 
| 04c1Tg0M |   1 | pdex  |   2 | id   | A   |  9275107 |  NULL | NULL |  | BTREE  |   | 
| 04c1Tg0M |   1 | pdex  |   3 | tried  | A   |  9275107 |  NULL | NULL | YES | BTREE  |   | 
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 

А вот выход из запроса в вопрос:

+---------+ 
| MIN(id) | 
+---------+ 
|  1 | 
+---------+ 
1 row in set (3.76 sec) 

мне нужно резко сократить время выполнения запросов. Любая помощь приветствуется.

+0

Можете ли вы опубликовать вывод 'EXPLAIN SELECT'? Знаете ли вы, какой процент строк имеет 'try = 0' против' try = 1'? –

ответ

6

Вам следует добавить индекс на (tried, id).

Вы уже указали индекс на (username,id,tried), но этот индекс не может быть эффективно использован для запрошенного вами запроса, поскольку поле tried не является первым элементом в индексе.


На странице ручного How MySQL Uses Indexes:

MySQL использует индексы для этих операций:

  • Чтобы найти значение MIN() или MAX() для конкретного индексированного столбца key_col. Это оптимизируется препроцессором, который проверяет, используете ли вы WHERE key_part_N = constant для всех ключевых частей, которые происходят до key_col в индексе. В этом случае MySQL выполняет один ключевой поиск для каждого выражения MIN() или MAX() и заменяет его константой. Если все выражения заменены на константы, запрос возвращается сразу. Например:

    SELECT MIN (key_part2), MAX (key_part2) FROM tbl_name WHERE key_part1 = 10;

Примечание, в частности, что положение WHERE должны ссылаться на столбцы, которые происходят перед столбец, для которого вы хотите вычислить MIN или MAX, поэтому текущий индекс эффективно не используется.


мне нужно быстро сделать выбор запросов по нему в цикле

Вы уверены, что вам нужно запросить в цикле? Рассматривали ли вы перемещение цикла в базу данных?Может, вам действительно нужно присоединиться? Лучше отправить один запрос, который извлекает много данных, чем множество небольших запросов, которые извлекают только небольшое количество данных.

+0

Я только что добавил вывод индексного указателя к своему сообщению. Не могли бы вы взглянуть, не кажется ли что-то неправильным? Кроме того, вы предлагаете создать второй составной индекс? – xendi

+0

Да, индексирование - лучший вариант для улучшения и ускорения работы в mysql qureies. – vimal

+0

@xendi: Вы не сказали, для чего нужен другой индекс. –

2

Добавление индекса в столбец tried должно ускорить ваши запросы. MySQL использует индексы для этих операций:

Чтобы найти значение MIN() или MAX() для определенного индексированного столбца key_col. Это оптимизируется препроцессором, который проверяет, используете ли вы WHERE key_part_N = constant во всех ключевых частях, которые происходят до key_col в индексе. В этом случае MySQL выполняет один ключевой поиск для каждого выражения MIN() или MAX() и заменяет его константой. Если все выражения заменены на константы, запрос возвращается сразу. Например:

SELECT MIN (key_part2), MAX (key_part2) FROM tbl_name WHERE key_part1 = 10;

0

Если вы добавите индекс в столбец tried, ваш запрос должен ускориться.

Вы можете использовать команду типа

create index tried_ix1 on 04c1Tg0M (tried); 

Как примечание стороны, если вы подаете индекс на таблицу InnoDB, пожалуйста, также рассмотреть вопрос о том, следует ли или не быть сгруппированы этот показатель. Например, если вы собираетесь получить доступ к большому количеству записей в таблице, в определенном, возможно, отсортированном порядке, возможно, для отчета, а затем подумайте о создании кластерного индекса на основе требований к сортировке этого отчета.

Смежные вопросы