Mysql полнотекстовый поиск вызывает высокую загрузку процессора
Мы создали новостной сайт. Каждый день мы будем вводить десятки тысяч данных из веб-API.
Чтобы обеспечить точный поиск, наша таблица использует MyISAM, создает полнотекстовый индекс (заголовок, контент, дата). Наш сайт теперь тестируется в Godaddy VDS с 2 ГБ ОЗУ, 30 ГБ пространства (без свопа, потому что VDS не позволяет создавать своп).
с #grep “model name” /proc/cpuinfo
мы используем Godaddy Intel(R) Xeon(R) CPU L5609 @ 1.87GHz
Вот наш ввод MySQL, используйте FROM dual
избегайте вставки повторяющейся записи, а индекс таблицы FULLTEXT всегда включен.
INSERT INTO newstable
(title,link,content,date,source,image,imagesource)
SELECT '".$title."','".$link."','','".$content."','".$date."','".$source."','".$image."','".$imagesource."'
FROM dual WHERE not exists
(SELECT content FROM newstable WHERE newstable.content = '".$content."')
Вот наш поисковый запрос на странице чтения (у нас есть оптимизация домашней страницы, это статическая страница, сгенерированная из crond, но страница чтения должна сохраняться для живого поиска):
SELECT id,title,link,content,date,source,image,imagesource
FROM newstable
WHERE (MATCH (title,content,date)
AGAINST ('$boolean' IN BOOLEAN MODE))
Order By date DESC Limit '.($_POST['number']).', 10
каждая страница имеет 2 или 3 запроса, как указано выше. (* Я переименовал имя таблицы и имя поля)
Для новостного сайта нам нужно держать свежие новости на верхнем сайте, поэтому sort by date
необходимо.
Теперь наша проблема: Mysql full text search will cause high usage CPU
, использование #top
для мониторинга сервера, открыть каждую страницу будет стоить 10% CPU
, Боюсь, что в этом случае наш сайт может одновременно поддерживать только несколько человек. Но наша цель - одновременно 100 человек онлайн. Большое спасибо.
Cpu(s): 10.4%us, 1.4%sy, 0.0%ni, 88.5%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 2097152k total, 570364k used, 1526788k free, 0k buffers
Swap: 0k total, 0k used, 0k free, 0k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
28265 mysql 15 0 385m 75m 5752 S 129.3 3.7 751:49.13 mysqld
1313 root 15 0 35040 18m 6400 S 7.0 0.9 0:03.55 php
1 root 15 0 2156 664 576 S 0.0 0.0 0:04.42 init
1215 root 15 -4 2260 652 436 S 0.0 0.0 0:00.00 udevd
1359 root 15 0 2240 1004 812 R 0.0 0.0 0:00.00 top
1585 root 25 0 2832 868 700 S 0.0 0.0 0:00.00 xinetd
...
РЕДАКТИРОВАТЬ: объяснить результат запроса:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY newstable fulltext index_name index_name 0 1 Using where
РЕДАКТИРОВАТЬ 2: ./mysqltuner.pl результат
-------- General Statistics --------------------------------------------------
[--] Skipped version check for MySQLTuner script
[OK] Currently running supported MySQL version 5.5.20
[OK] Operating on 32-bit architecture with less than 2GB RAM
-------- Storage Engine Statistics -------------------------------------------
[--] Status: -Archive -BDB -Federated +InnoDB -ISAM -NDBCluster
[--] Data in MyISAM tables: 396M (Tables: 39)
[--] Data in InnoDB tables: 208K (Tables: 8)
[!!] Total fragmented tables: 9
-------- Security Recommendations -------------------------------------------
[!!] User '@ip-XX-XX-XX-XX.ip.secureserver.net'
[!!] User '@localhost'
-------- Performance Metrics -------------------------------------------------
[--] Up for: 17h 27m 58s (1M q [20.253 qps], 31K conn, TX: 513M, RX: 303M)
[--] Reads / Writes: 61% / 39%
[--] Total buffers: 168.0M global + 2.7M per thread (151 max threads)
[OK] Maximum possible memory usage: 573.8M (28% of installed RAM)
[OK] Slow queries: 0% (56/1M)
[!!] Highest connection usage: 100% (152/151)
[OK] Key buffer size / total MyISAM indexes: 8.0M/162.5M
[OK] Key buffer hit rate: 100.0% (2B cached / 882K reads)
[!!] Query cache is disabled
[OK] Sorts requiring temporary tables: 0% (0 temp sorts / 17K sorts)
[!!] Temporary tables created on disk: 49% (32K on disk / 64K total)
[!!] Thread cache is disabled
[!!] Table cache hit rate: 0% (400 open / 298K opened)
[OK] Open file limit used: 41% (421/1K)
[!!] Table locks acquired immediately: 77%
[OK] InnoDB data size / buffer pool: 208.0K/128.0M
-------- Recommendations -----------------------------------------------------
General recommendations:
Run OPTIMIZE TABLE to defragment tables for better performance
MySQL started within last 24 hours - recommendations may be inaccurate
Enable the slow query log to troubleshoot bad queries
Reduce or eliminate persistent connections to reduce connection usage
When making adjustments, make tmp_table_size/max_heap_table_size equal
Reduce your SELECT DISTINCT queries without LIMIT clauses
Set thread_cache_size to 4 as a starting value
Increase table_cache gradually to avoid file descriptor limits
Optimize queries and/or use InnoDB to reduce lock wait
Variables to adjust:
max_connections (> 151)
wait_timeout (< 28800)
interactive_timeout (< 28800)
query_cache_size (>= 8M)
tmp_table_size (> 16M)
max_heap_table_size (> 16M)
thread_cache_size (start at 4)
table_cache (> 400)
РЕДАКТИРОВАТЬ 3: my.cnf
[mysqld]
port = 3306
socket = /tmp/mysql.sock
skip-external-locking
key_buffer_size = 256M
max_allowed_packet = 16M
max_connections = 1024
wait_timeout = 5
table_open_cache = 512
sort_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 2M
myisam_sort_buffer_size = 128M
thread_cache_size = 8
query_cache_size= 256M
# Try number of CPU's*2 for thread_concurrency
thread_concurrency = 8
ft_min_word_len = 2
read_rnd_buffer_size=2M
tmp_table_size=128M
3 ответа
Несколько странных вещей выделяются здесь.
- Ваша система простаивает на 94,5%, а MySQL использует 129% вашего процессора. Там что-то очень странное.
- MySQL использует только 3% доступной памяти. Я также вижу, что там запущен PHP-процесс, поэтому я предполагаю, что это комбинированная сеть и база данных, но, тем не менее, я ожидаю, что вы дадите больше оперативной памяти MySQL, просто убедитесь, что оставлено достаточно для веб-процессов.
Возьмите mysqltuner.pl (просто введите wget mysqltuner.pl
) и запустите его через вашу базу данных. Скорее всего, будет несколько хороших предложений.
В любом случае, полнотекстовый поиск MySQL не является правильным способом справиться с этим. Sphinx или Lucene - хорошие проекты для поиска.
Я не уверен, что вы можете сделать что-либо, полнотекстовый поиск mysql не очень хорош в моем опыте.
Простые решения.
- запустить меньше запросов. полнотекстовый поиск мамы на просмотр страницы будет дорогим для процессора.
- Перепроектируйте свою базу данных / приложение так, чтобы вы обновляли некую индексную таблицу при вставке контента, а не при просмотре страницы. Кажется расточительным делать много поисков за просмотр страницы.
- купить больше оборудования, чтобы вы могли поддерживать свой текущий дизайн
- используйте что-то другое, чем mysql для полнотекстового поиска. Возможно, что-то основано на Lucene?
Похоже, вы не используете индекс на то, что вы ищете.. добавить explain
перед запросом и вставьте результаты.