2014-01-28 4 views
0

У меня есть InnoDB таблицы, около 1000000 строк:запрос с использованием, как 'термин%%' очень медленно

Data   164.7 MiB 
Index   250.1 MiB 
Overhead  168.0 MiB 
Effective  246.8 MiB 
Total   414.8 MiB 

Структура таблицы:

CREATE TABLE IF NOT EXISTS `gift` (
    `tm` varchar(15) NOT NULL, 
    `col` smallint(2) NOT NULL, 
    `myindex` varchar(255) NOT NULL, 
    `date` int(10) NOT NULL, 
    KEY `tm` (`tm`), 
    KEY `date` (`date`), 
    KEY `myindex` (`myindex`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

tm является не-дубликат строки генерируется PHP (продукты ID),

date магазин использование strtotime('now'),

myindex магазин поиск ключевых слов

, потому что некоторые продукты имеют длинные описания (более 255 символов), так col это отдельные длинные описания со многими частями (одни и те же продукты, ключевые слова часть 1, часть 2 ключевые слова ...).

Запрос, как это сделать (10 Всего запросов занял 51.0829 сек)

SELECT * 
FROM gift 
WHERE myindex LIKE '% keywords1 %' 
AND myindex LIKE '% keywords2 %' 
GROUP BY tm 
ORDER BY DATE DESC 
LIMIT 10 

сделать объяснить, что получите:

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE  gift index NULL   date 4 NULL 10 Using where; Using temporary 

possible_keys имеет нулевое значение, ли я сделал плохой индекс ? Как сделать это быстрее всего?

здесь my.cnf, мой сервер имеет 4 ГБ оперативной памяти, mysql также поддерживает полнотекстовый поиск.

И я попробовал установить key_buffer_size и innodb_buffer_pool_size на 512 МБ, но сервер легко сбой с предупреждением apache child process still did not exit sending a sigterm. Должен ли я оставить как минимум 1 ГБ оперативной памяти для системы и apache? (Только около 2,5-3 ГБ для my.cnf?)

[mysqld] 
character_set_server=utf8 
port  = 3306 
socket  = /var/lib/mysql/mysql.sock 
skip-external-locking 
skip-networking 
key_buffer = 256M 
tmp_table_size = 64M 
max_connections = 300 
wait_timeout=15 
back_log = 2048 
key_buffer_size = 384M 
max_allowed_packet = 2M 
table_cache = 2048 
table_open_cache = 2048 
sort_buffer_size = 6M 
read_buffer_size = 4M 
net_buffer_length = 92K 
read_rnd_buffer_size = 4M 
myisam_sort_buffer_size = 256M 
thread_cache = 384 
query_cache_size= 256M 
bulk_insert_buffer_size = 192M 
ft_min_word_len=2 
skip-networking 

binlog_format=mixed 

innodb_buffer_pool_size = 384M 
innodb_buffer_pool_instances=4 

innodb_use_sys_malloc = 0 

[mysqldump] 
quick 
max_allowed_packet = 8M 

[mysql] 
no-auto-rehash 

[myisamchk] 
key_buffer_size = 96M 
sort_buffer_size = 96M 
read_buffer = 3M 
write_buffer = 3M 
+1

Использование '%' в начале исключает использование ключей. –

+0

@Bart Friederichs, так как сделать такой поиск и сделать индексный эффект? – cj333

+0

Не используйте 'LIKE'. Поместите поисковые слова в другую таблицу и сделайте ссылку или что-то в этом роде. –

ответ

0

Прежде всего, вы используете незаконную группировку. проверить первый абзац http://dev.mysql.com/doc/refman/5.0/en/group-by-extensions.html

Во-вторых, кажется, что группе даже не требуется, и вызывает ваш «временный», чтобы показать пояснениями

В-третьих, (не цитируйте меня о NThis, а не 100% конечно) ваш tempary tmp_table_size = 64M может быть слишком мал для этого запроса, так как он сохраняет отфильтрованные результаты в памяти до группировки

4-й, если вам нужно сгруппировать, назначьте целое число для этой строки и сгруппируйте по целому числу ,

5th, если у вас есть ключевые слова, сохраните их в таблице ключевых слов и используйте их для соединения. Вы получите некоторое повышение производительности благодаря соединению, но это позволит вам использовать индекс. Индексы только вступают в игру, когда вы сравниваете строки с самого начала (и, следовательно, используя длину 6-10 индекса VARCHAR могут быть столь же эффективными, как использование индекса 100 длины)

счастливого оптимизируя :)

1

Действительных проблема в том, что MySQL не может использовать индекс для такого состояния, как myindex LIKE '% keywords1 %'. Эта тема широко распространена в Интернете, поэтому я предлагаю вам искать полнотекстовое индексирование. Вы можете использовать либо один внутренний (индексы в MySQL), либо внешний (Sphinx, Lucene и т. Д.).

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