Я сталкиваюсь с некоторыми проблемами с быстро растущей таблицей с увеличивающейся скоростью (в настоящее время 4 миллиона строк, 300 тысяч вставок в день). Я надеюсь, что смогу получить некоторые идеи и советы здесь, чтобы улучшить мою настройку и выжать последний бит из моей коробки, прежде чем он закроет мой сайт в ближайшем будущем.
Настройка:
Intel i7 720
8GB RAM
2x750GB SATA RAID 0
CentOS
MySQL 5.5.10
Node.js + node-lib_mysql-client
Определение таблицы:
CREATE TABLE IF NOT EXISTS `canvas` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`x1` int(11) NOT NULL,
`y1` int(11) NOT NULL,
`x2` int(11) NOT NULL,
`y2` int(11) NOT NULL,
`c` int(4) unsigned NOT NULL,
`s` int(3) unsigned NOT NULL,
`m` bigint(20) unsigned NOT NULL,
`r` varchar(32) NOT NULL,
PRIMARY KEY (`id`,`x1`,`y1`) KEY_BLOCK_SIZE=1024,
KEY `x1` (`x1`,`y1`) KEY_BLOCK_SIZE=1024,
KEY `x2` (`x2`,`y2`) KEY_BLOCK_SIZE=1024
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=COMPACT KEY_BLOCK_SIZE=4
/*!50100 PARTITION BY HASH ( (
(
x1 MOD 10000
)
) + y1 MOD 10000)
PARTITIONS 10 */ AUTO_INCREMENT=13168904 ;
Запрос:
SELECT x1,y1,x2,y2,s,c,r,m FROM canvas
WHERE 1 AND ((
x1 >= 0
AND x1 <= 400
AND y1 >= 0
AND y1 <= 400
) OR (
x2 >= 0
AND x2 <= 400
AND y2 >= 0
AND y2 <= 400
) )
ORDER BY id desc
Это единственный запрос, который я выполняю, за исключением того факта, что значения x1, y1, x2 и y2 меняются в каждом запросе. Это 2D холст, и каждая строка представляет линию на холсте. Думаю, также важно знать, что максимальный диапазон, выбранный для 1 поля, никогда не превышает 1200 (пикселей).
Несколько недель назад я обновился до MySQL 5.5.10 и начал использовать разделы. Хэш 'x1% 10000' - мой первый и неосведомленный подход к теме раздела. Это уже дало мне приличный прирост скорости SELECT, но я уверен, что еще есть место для оптимизации.
Да, и прежде чем вы спросите ... Я знаю, что я использую таблицу MyISAM. Мой друг предложил innoDB, но уже попробовал, и в результате получилось увеличение таблицы в 2 раза и падение производительности SELECT. Мне не нужны никакие причудливые транзакции и прочее ... все, что мне нужно, это наилучшая возможная производительность SELECT и достойная производительность с INSERT.
Что бы вы изменили? Могу ли я как-нибудь настроить свои индексы? Имеет ли смысл установка моих разделов вообще? Должен ли я, возможно, увеличить количество файлов разделов?
Все предложения приветствуются ... Я также обсуждал локальную репликацию в таблицу памяти с другом, но я уверен, что это только вопрос времени, пока размер таблицы не превысит мою оперативную память, а поле подкачки - довольно некрасивая вещь.
Когда вы думаете о моей проблеме, имейте в виду, что она быстро и непредсказуемо растет. Если по какой-то причине он окажется где-то вирусным, я ожидаю увидеть более 1 миллиона вкладок в день.
Спасибо, что читаете и думаете об этом. :)
РЕДАКТИРОВАТЬ: Запрошенный результат EXPLAIN
select_type table type possible_keys key key_len ref rows Extra
SIMPLE canvas index_merge x1,x2 x1,x2 8,8 NULL 133532 Using sort_union(x1,x2); Using where; Using fileso...
EDIT2: запрошенный my.cnf
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
innodb_buffer_pool_size = 1G
sort_buffer_size = 4M
read_buffer_size = 1M
read_rnd_buffer_size = 16M
innodb_file_format = Barracuda
query_cache_type = 1
query_cache_size = 100M
# http://dev.mysql.com/doc/refman/5.5/en/performance-schema.html
;performance_schema
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
Значения innoDB для моей попытки innoDB ... думаю, они больше не нужны. Сервер также управляет 4 другими веб-сайтами, но они довольно малы и не заслуживают упоминания. Я все равно скоро перенесу этот проект в специальную коробку. Ваши идеи могут быть радикальными - я не против экспериментов.
EDIT3 - ЭТАЛОНЫ С ИНДЕКСАМИ
Хорошо, ребята ... Я сделал несколько тестов с разными индексами, и результаты пока довольно хорошие. Для этого теста я выбрал все строки в блоке размером 2000x2000 пикселей.
SELECT SQL_NO_CACHE x1,y1,x2,y2,s,c FROM canvas_test WHERE 1 AND (( x1 BETWEEN -6728 AND -4328 AND y1 BETWEEN -6040 AND -4440 ) OR ( x2 BETWEEN -6728 AND -4328 AND y2 BETWEEN -6040 AND -4440 ) ) ORDER BY id asc
Используя определение таблицы / индекса, которое я разместил выше, среднее время запроса было: 1740ms
Затем я отбросил все индексы, кроме первичного ключа -> 1900ms
добавлен один индекс для x1 -> 1800 мс
добавлен один индекс для y1 -> 1700 мс
добавлен один индекс для x2 -> 1500 мс
добавлен один индекс для y2 -> 900 мс!
Пока что это удивительно ... почему-то я думал, что создание комбинированных индексов для x1 / y1 и x2 / y2 имело бы смысл, но на самом деле это выглядит так, как будто я ошибался.
EXPLAIN теперь возвращает это:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE canvas_test index_merge x1,y1,x2,y2 y1,y2 4,4 NULL 263998 Using sort_union(y1,y2); Using where; Using fileso..
Теперь мне интересно, почему он использует y1 / y2 в качестве ключей, а не все четыре?
Однако я все еще ищу больше идей и советов, особенно относительно разделов и правильного хеширования.