Поскольку это мой первый пост, кажется, я могу опубликовать только 1 ссылку, поэтому я перечислил сайты, на которые я ссылаюсь, внизу. В двух словах, моя цель - сделать так, чтобы база данных возвращала результаты быстрее, я постарался включить как можно больше необходимой информации, чтобы помочь сформулировать вопросы в нижней части поста.
Информация о машине
8 processors
model name : Intel(R) Xeon(R) CPU E5440 @ 2.83GHz
cache size : 6144 KB
cpu cores : 4
top - 17:11:48 up 35 days, 22:22, 10 users, load average: 1.35, 4.89, 7.80
Tasks: 329 total, 1 running, 328 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.0%us, 0.0%sy, 0.0%ni, 87.4%id, 12.5%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 8173980k total, 5374348k used, 2799632k free, 30148k buffers
Swap: 16777208k total, 6385312k used, 10391896k free, 2615836k cached
Однако мы собираемся перенести установку mysql на другую машину в кластере с 256 ГБ ОЗУ
Таблица информации
Моя таблица MySQL выглядит как
CREATE TABLE ClusterMatches
(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
cluster_index INT,
matches LONGTEXT,
tfidf FLOAT,
INDEX(cluster_index)
);
В нем приблизительно 18 миллионов строк, есть 1 миллион уникальных совпадений cluster_index и 6 тысяч уникальных совпадений. SQL-запрос, который я генерирую в PHP выглядит так.
SQL-запрос
$sql_query="SELECT `matches`,sum(`tfidf`) FROM
(SELECT * FROM Test2_ClusterMatches WHERE `cluster_index` in (".$clusters."))
AS result GROUP BY `matches` ORDER BY sum(`tfidf`) DESC LIMIT 0, 10;";
где $ cluster содержит строку из 3000 разделенных запятыми cluster_index's. Этот запрос использует приблизительно 50000 строк и выполняется приблизительно 15 секунд, а при повторном запуске того же запроса требуется приблизительно 1 секунда.
Использование
- Содержание таблицы можно считать статическим.
- Небольшое количество одновременных пользователей
- Вышеприведенный запрос в настоящее время является единственным запросом, который будет выполняться в таблице
подзапросы
На основании этого поста [stackoverflow: Cache / Re-Use a Subquery в MySQL] [1] и улучшения времени запроса, я считаю, что мой подзапрос может быть проиндексирован.
mysql> EXPLAIN EXTENDED SELECT `matches`,sum(`tfidf`) FROM
(SELECT * FROM ClusterMatches WHERE `cluster_index` in (1,2,...,3000)
AS result GROUP BY `matches` ORDER BY sum(`tfidf`) ASC LIMIT 0, 10;
+----+-------------+----------------------+-------+---------------+---------------+---------+------+-------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------------------+-------+---------------+---------------+---------+------+-------+---------------------------------+
| 1 | PRIMARY | derived2 | ALL | NULL | NULL | NULL | NULL | 48528 | Using temporary; Using filesort |
| 2 | DERIVED | ClusterMatches | range | cluster_index | cluster_index | 5 | NULL | 53689 | Using where |
+----+-------------+----------------------+-------+---------------+---------------+---------+------+-------+---------------------------------+
В соответствии с этой более старой статьей [Оптимизация MySQL: запросы и индексы] [2] в разделе Дополнительная информация - плохие, которые можно увидеть здесь, "используют временные" и "используют файловую сортировку"
Информация о конфигурации MySQL
Кэш запросов доступен, но фактически отключен, так как размер в настоящее время установлен на ноль
mysqladmin variables;
+---------------------------------+----------------------+
| Variable_name | Value |
+---------------------------------+----------------------+
| bdb_cache_size | 8384512 |
| binlog_cache_size | 32768 |
| expire_logs_days | 0 |
| have_query_cache | YES |
| flush | OFF |
| flush_time | 0 |
| innodb_additional_mem_pool_size | 1048576 |
| innodb_autoextend_increment | 8 |
| innodb_buffer_pool_awe_mem_mb | 0 |
| innodb_buffer_pool_size | 8388608 |
| join_buffer_size | 131072 |
| key_buffer_size | 8384512 |
| key_cache_age_threshold | 300 |
| key_cache_block_size | 1024 |
| key_cache_division_limit | 100 |
| max_binlog_cache_size | 18446744073709547520 |
| sort_buffer_size | 2097144 |
| table_cache | 64 |
| thread_cache_size | 0 |
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 0 |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
| read_rnd_buffer_size | 262144 |
+---------------------------------+----------------------+
На основании этой статьи [Поворот производительности базы данных Mysql] [3] я считаю, что значения, которые мне нужно настроить, равны
- table_cache
- key_buffer
- sort_buffer
- read_buffer_size
- record_rnd_buffer (для условий GROUP BY и ORDER BY)
Области, определенные для улучшения - настройки MySQL Query
- Изменение типа данных для совпадений с индексом, который является целым числом, указывающим на другую таблицу [MySQL действительно будет использовать динамический формат строки, если он содержит поля переменной длины, такие как TEXT или BLOB, что в данном случае означает, что сортировка должна выполняться сделано на диске. Решение состоит не в том, чтобы избежать этих типов данных, а в том, чтобы разбить такие поля на связанную таблицу.] [4]
- Индексирование нового поля match_index так, чтобы GROUP BY
matches
происходило быстрее, основываясь на выражении [«Вам, вероятно, следует создать индексы для любого поля, в котором вы выбираете, группируете, упорядочиваете или объединяете».] [5 ]
Инструменты
Для настройки исполнения планирую использовать
- [Объяснить] [6] со ссылкой на [выходной формат] [7]
- [ab - инструмент тестирования Apache HTTP-сервера] [8]
- [Профилирование] [9] с [данными журнала] [10]
Размер базы данных будущего
Цель состоит в том, чтобы создать систему, которая может иметь 1М уникальных значений cluster_index, 1М уникальных значений соответствия, около 3 000 000 000 строк таблицы с временем ответа на запрос около 0,5 с (мы можем добавить больше оперативной памяти при необходимости и распределить базу данных по кластер)
Вопросы
- Я думаю, что мы хотим сохранить весь набор записей в оперативной памяти, чтобы запрос не касался диска. Если мы храним всю базу данных в кэше MySQL, устраняет ли это необходимость в memcachedb?
- Является ли попытка сохранить всю базу данных в кеше MySQL плохой стратегией, поскольку она не предназначена для постоянной работы? Будет ли лучше использовать что-то вроде memcachedb или redis, если да, то почему?
- Является ли временная таблица «результатом», созданная запросом, автоматически уничтожается после его завершения?
- Должны ли мы переключиться с Innodb на MyISAM [это хорошо для чтения тяжелых данных, где InnoDB хорош для тяжелой записи] [11]?
- мой кэш не отображается как ноль в моем [Конфигурация кеша запросов] [12], почему в данный момент запрос выполняется быстрее при втором запуске?
- Могу ли я реструктурировать свой запрос, чтобы исключить возникновение "использования временного" и "использования файловой сортировки", если я буду использоватьобъединение вместо подзапроса?
- как вы оцениваете размер MySQL [Data Cache] [13]?
- какие размеры для значений table_cache, key_buffer, sort_buffer, read_buffer_size, record_rnd_buffer вы бы предложили в качестве отправной точки?
Ссылки
- 1: stackoverflow.com/questions/658937/cache-re-use-a-подзапрос в mysql
- 2: databasejournal.com/features/mysql/article.php/10897_1382791_4/Optimizing-MySQL-Queries-and-Indexes.htm
- 3: debianhelp.co.uk / mysqlperformance.htm
- 4: 20bits.com/articles/10-tips-for-optimizing-mysql-query-that-dont-suck /
- 5: 20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck/
- 6: dev.mysql.com/doc/refman/5.0/en/explain.html
- 7: dev.mysql.com/doc/refman/5.0/en/explain-output.html
- 8: httpd.apache.org/docs/2.2/programs/ab.html
- 9: mtop.sourceforge.net/
- 10: dev.mysql.com/doc / refman / 5.0 / en / slow-query-log.html
- 11: 20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck/
- 12: dev.mysql.com/doc/refman/5.0/en/query-cache-configuration.html
- 13: dev.mysql.com/tech-resources/articles/mysql-query-cache.html