MySQL Slow Writes

8

Вставки в следующую таблицу занимают до 70 секунд:

CREATE TABLE IF NOT EXISTS `productsCategories` (
  `categoriesId` int(11) NOT NULL,
  `productsId` int(11) NOT NULL,
  PRIMARY KEY (`categoriesId`,`productsId`),
  KEY `categoriesId` (`categoriesId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

В таблице около 100 000 строк, и она занимает 7 МБ на диске.

Есть ли в MySQL некоторые настройки, которые могут улучшить производительность записи?

Мой my.cnfфайл выглядит следующим образом:

log-slow-queries="/var/log/mysql/slow-query.log"
long_query_time=1 
log-queries-not-using-indexes

innodb_buffer_pool_size=4G
innodb_log_buffer_size=4M
innodb_flush_log_at_trx_commit=2
innodb_thread_concurrency=8
innodb_flush_method=O_DIRECT

query_cache_size = 6G
key_buffer_size = 284M
query_cache_limit = 1024M
thread_cache_size = 128
table_cache = 12800

sort_buffer_size=2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M

read_buffer_size=128K

open_files_limit               = 1000
table_definition_cache         = 1024
table_open_cache               = 6000

max_heap_table_size=512M
tmp_table_size=4096M

max_connections=1000

thread_concurrency = 24

Вот аппаратная настройка:

  • Dell R710
  • RAID10
  • 48 ГБ ОЗУ

Учитывая это оборудование, я не ожидал бы, что проблема будет аппаратным узким местом.

Ronn0
источник
Можете ли вы предоставить некоторые объективные данные? Журналы, ваша методология и результаты тестирования / тестирования, и тому подобное?
Уомбл
Какие журналы вы хотели бы видеть? Единственное, что я понимаю, почему так долго, это в de mtop . Я бы протестировал вещи, как изменить таблицу на таблицу myisam, более высокие ограничения памяти, более высокие потоки.
Ronn0
Лучшая настройка для улучшения mysql ... это переключиться на postgres lol
Энтони Гиббс
thread_concurrency = 24 не имеет никакого эффекта ... вы можете сбросить эту строку
Энтони Гиббс

Ответы:

16

НАБЛЮДЕНИЕ № 1

Первое, что бросается в глаза, - это структура стола.

CREATE TABLE IF NOT EXISTS `productsCategories` (
  `categoriesId` int(11) NOT NULL,
  `productsId` int(11) NOT NULL,
  PRIMARY KEY (`categoriesId`,`productsId`),
  KEY `categoriesId` (`categoriesId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Обратите внимание, что categoriesIdиндекс и ПЕРВИЧНЫЙ КЛЮЧ начинаются с одного столбца. Это избыточный индекс. Поскольку эта таблица InnoDB, categoriesIdиндекс является избыточным по другой причине: все вторичные индексы содержат ключи в gen_clust_index (он же Clustered Index; посмотрите, для чего используется gen_clust_index в mysql? )

Если вы удалите categoriesIdиндекс с

ALTER TABLE productsCategories DROP INDEX categoriesId;

это улучшит оператор INSERT резко из - за не приходится делать дополнительное вторичное и кластерное индекс обслуживание.

НАБЛЮДЕНИЕ № 2

Если вы выполняете какие-либо операции массовой вставки, вам нужен большой буфер массовой вставки .

Пожалуйста, смотрите мои прошлые сообщения на это:

НАБЛЮДЕНИЕ № 3

Ваш размер файла журнала слишком мал !!! Это должно быть 25% пула буферов InnoDB, который в вашем случае должен быть 1G. Смотрите мой пост о том, как изменить размер InnoDB Log Files .

НАБЛЮДЕНИЕ № 4

Пожалуйста, не устанавливайте innodb_thread_concurrency !!! Я узнал из первых рук в Percona Live NYC, чтобы оставить эту обстановку в покое . По умолчанию он отключен в MySQL 5.5, подключаемом модуле MySQL 5.1 InnoDB и Percona Server 5.1+.

НАБЛЮДЕНИЕ № 5

Вам нужно использовать innodb_file_per_table. Если это отключено, я делаю обслуживание файлов на ibdata1 кошмаром. Пожалуйста, прочитайте мой пост о том, как очистить InnoDB для реализации этого .

НАБЛЮДЕНИЕ № 6

Если вы используете MySQL 5.5 или Percona Server, вам нужно установить определенные параметры, чтобы InnoDB использовал несколько процессоров / несколько ядер. Пожалуйста, смотрите мой пост об этих настройках .

НАБЛЮДЕНИЕ № 7

У вас есть innodb_log_buffer_size=4M. По умолчанию это 8M. Это приведет к вдвое большему количеству сброса в журналы повторов. Это также противодействует вашей innodb_flush_log_at_trx_commit=2настройке. Пожалуйста, установите его на 32M. Также, пожалуйста, смотрите документацию MySQL по адресу innodb_log_buffer_size .

В свете этих замечаний добавьте или замените следующие параметры:

[mysqld]
innodb_thread_concurrency = 0
innodb_read_io_threads = 64
innodb_write_io_threads = 64
innodb_io_capacity = 5000
innodb_file_per_table
innodb_log_file_size=1G
innodb_log_buffer_size=1G
bulk_insert_buffer_size = 256M
RolandoMySQLDBA
источник
Вау, спасибо! Я напечатал все пункты и работал над этим сейчас и сохранил его в мозгу, чтобы помочь другим людям в будущем. Большое спасибо!
Ronn0
2
query_cache_sizeтоже огромен. Каждая вставка требует до 6 ГБ кеша для очистки.
Аарон Браун
@AaronBrown Я согласен. В книге по высокопроизводительной MySQL я читал, что InnoDB делает утомительные действия с идентификатором транзакции в таблице InnoDB в кеше запросов, что делает его использование ненужным, не говоря уже о медленном использовании кеша запросов. Фактически в MySQL 4.1 отключен кэш запросов для InnoDB.
RolandoMySQLDBA
Я думаю, что кеш запросов полностью отделен от механизма хранения. Он в основном сериализует все операции записи, заставляя все проходить и сканировать кеш запросов для запросов на недействительность. Я никогда не нашел вариант использования для него, и это всегда вызывало проблемы.
Аарон Браун
Еще одна вещь, которую нужно добавить: query_cache_size = 6G <- это абсолютно и совершенно абсурдно. Кэш запросов часто лучше отключать, и он не должен быть больше 32М или 64М. Затраты на поддержание кеша запросов 6G, безусловно, снижают производительность.
Гэвин Тоуи
0

Вы должны проверить innodb_log_file_size, по умолчанию установлено значение 5M, что довольно мало для интенсивной записи. Попробуйте установить его на 100M. Вам придется удалить старые ib_logfile*файлы, чтобы запустить БД с новыми настройками. Пожалуйста, не удаляйте файлы журналов во время работы сервера БД, вам придется сначала остановить его. Возможно, вам следует сначала сделать резервную копию старых файлов журнала, а не просто удалить их.

Alex
источник