Производительность MySQL? - PullRequest
       8

Производительность MySQL?

0 голосов
/ 10 октября 2018

У меня есть две основные таблицы на сервере, с одинаковой структурой и данными (единственное отличие - в именах таблиц).

Таблица № 1: 214 миллионов строк, размер 40 ГБ (индексы 25 ГБ)

Таблица №2: 26 миллионов строк, размер 5,5 ГБ (индексы 3,5 ГБ)

Первая проблема.Все работает очень быстро, когда в памяти есть кеш.Если я очищаю кеш или перезагружаю сервер, то запросы mysql идут очень медленно.Debian 8 Джесси.MySQL хранит индексы в памяти и всегда принимает их в качестве кэша?Потому что после некоторых манипуляций запросы select выполняются очень быстро.Какие манипуляции необходимо выполнить, чтобы сервер работал:

Если я использую дубликат таблицы № 1, то во время ее выполнения, насколько я понимаю, происходит операция чтения, и в то же время информация кэшируется.в память.Вот экран free -m в момент запуска дублирующейся таблицы.

root@ns344370:~# free -m
             total       used       free     shared    buffers     cached
Mem:        128965      76802      52163         31         61      21714
-/+ buffers/cache:      55026      73939
Swap:        56141          0      56141

Результат, когда была создана дублирующаяся таблица:

root@ns344370:~# free -m
             total       used       free     shared    buffers     cached
Mem:        128965     126414       2551         31         49      65426
-/+ buffers/cache:      60938      68027
Swap:        56141          0      56141

50 ГБ оперативной памяти под кешем.Выполнение запроса до дубликата таблицы 105 секунд:

# Query_time: 105.469931  Lock_time: 0.000180 Rows_sent: 41041  Rows_examined: 2097994
SET timestamp=1539135133;
SELECT SQL_CACHE `id`, `currency`, `handLimit`, `date`, `pp1` AS `profit`,`psd1` AS `isSD` FROM `ps_hands` WHERE `p1` = '274606' AND (`date` >= '2018-10-01' AND `date` <= '2018-10-10') 
UNION ALL (SELECT `id`, `currency`, `handLimit`, `date`, `pp2` AS `profit`, `psd2` AS `isSD` FROM `ps_hands` WHERE `p2` = '274606' AND (`date` >= '2018-10-01' AND `date` <= '2018-10-10')) 
UNION ALL (SELECT `id`, `currency`, `handLimit`, `date`, `pp3` AS `profit`, `psd3` AS `isSD` FROM `ps_hands` WHERE `p3` = '274606' AND (`date` >= '2018-10-01' AND `date` <= '2018-10-10')) 
UNION ALL (SELECT `id`, `currency`, `handLimit`, `date`, `pp4` AS `profit`, `psd4` AS `isSD` FROM `ps_hands` WHERE `p4` = '274606' AND (`date` >= '2018-10-01' AND `date` <= '2018-10-10')) 
UNION ALL (SELECT `id`, `currency`, `handLimit`, `date`, `pp5` AS `profit`, `psd5` AS `isSD` FROM `ps_hands` WHERE `p5` = '274606' AND (`date` >= '2018-10-01' AND `date` <= '2018-10-10')) 
UNION ALL (SELECT `id`, `currency`, `handLimit`, `date`, `pp6` AS `profit`, `psd6` AS `isSD` FROM `ps_hands` WHERE `p6` = '274606' AND (`date` >= '2018-10-01' AND `date` <= '2018-10-10')) 
UNION ALL (SELECT `id`, `currency`, `handLimit`, `date`, `pp7` AS `profit`, `psd7` AS `isSD` FROM `ps_hands` WHERE `p7` = '274606' AND (`date` >= '2018-10-01' AND `date` <= '2018-10-10')) 
UNION ALL (SELECT `id`, `currency`, `handLimit`, `date`, `pp8` AS `profit`, `psd8` AS `isSD` FROM `ps_hands` WHERE `p8` = '274606' AND (`date` >= '2018-10-01' AND `date` <= '2018-10-10')) 
UNION ALL (SELECT `id`, `currency`, `handLimit`, `date`, `pp9` AS `profit`, `psd9` AS `isSD` FROM `ps_hands` WHERE `p9` = '274606' AND (`date` >= '2018-10-01' AND `date` <= '2018-10-10')) 
ORDER BY `id` ASC;

После дубликата таблицы его 0,2 секунды вместо 105 секунд.Я думаю о смене диска с SSHD на NVMe M2 (в 5 раз быстрее).Но у меня будет еще 4-5 таблиц по 50 ГБ каждая, в этом случае мне просто не хватает оперативной памяти.Как быть?У меня 128 ГБ ОЗУ.В дополнение к этому проекту, есть еще один проект.На которые выделено 50ГБ.Остальное используется для этого проекта и MySQL.Я использую MyISAM, а не InnoDB, потому что на сайте только выбирает и вставляет операции.InnoDB работает в 20 раз медленнее, также проверяется на домашней машине с диском M.2 .... А вот файл конфигурации mysql:

[client]
port        = 3306
socket      = /var/run/mysqld/mysqld.sock

[mysqld_safe]
socket      = /var/run/mysqld/mysqld.sock
nice        = 0

[mysqld]
user        = mysql
pid-file    = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
port        = 3306
basedir     = /usr
datadir     = /var/lib/mysql
tmpdir      = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
query_cache_type = DEMAND

key_buffer_size = 55G
sort_buffer_size = 512M
read_buffer_size = 128M

max_allowed_packet = 32M
thread_stack        = 192K
thread_cache_size       = 4096

#MySQL Tuner
max_heap_table_size = 128M
tmp_table_size = 128M
table_open_cache = 4096

myisam-recover         = BACKUP
max_connections        = 2000
table_cache            = 2048
thread_concurrency     = 17
query_cache_limit   = 128M
query_cache_size  = 256M

log_slow_queries  = /var/log/mysql/mysql-slow.log
long_query_time   = 1
#log-queries-not-using-indexes

expire_logs_days    = 10
max_binlog_size         = 100M
#binlog_do_db       = include_database_name
#binlog_ignore_db   = include_database_name

innodb_buffer_pool_size = 512M

[mysqldump]
quick
quote-names
max_allowed_packet  = 16M

[mysql]
#no-auto-rehash # faster start of mysql but no tab completition

[isamchk]
key_buffer      = 256M
!includedir /etc/mysql/conf.d/

Есть идеи?Пожалуйста.

Таблица DDL:

CREATE TABLE `ps_hands` (
  `id` bigint(14) NOT NULL DEFAULT '0',
  `currency` tinyint(1) NOT NULL,
  `handLimit` smallint(5) NOT NULL DEFAULT '0',
  `date` date NOT NULL,
  `maxPlayers` tinyint(1) NOT NULL,
  `p1` mediumint(7) NOT NULL DEFAULT '0',
  `p2` mediumint(7) NOT NULL DEFAULT '0',
  `p3` mediumint(7) NOT NULL DEFAULT '0',
  `p4` mediumint(7) NOT NULL DEFAULT '0',
  `p5` mediumint(7) NOT NULL DEFAULT '0',
  `p6` mediumint(7) NOT NULL DEFAULT '0',
  `p7` mediumint(7) NOT NULL DEFAULT '0',
  `p8` mediumint(7) NOT NULL DEFAULT '0',
  `p9` mediumint(7) NOT NULL DEFAULT '0',
  `pp1` mediumint(7) NOT NULL,
  `pp2` mediumint(7) NOT NULL,
  `pp3` mediumint(7) NOT NULL,
  `pp4` mediumint(7) NOT NULL,
  `pp5` mediumint(7) NOT NULL,
  `pp6` mediumint(7) NOT NULL,
  `pp7` mediumint(7) NOT NULL,
  `pp8` mediumint(7) NOT NULL,
  `pp9` mediumint(7) NOT NULL,
  `psd1` tinyint(1) NOT NULL,
  `psd2` tinyint(1) NOT NULL,
  `psd3` tinyint(1) NOT NULL,
  `psd4` tinyint(1) NOT NULL,
  `psd5` tinyint(1) NOT NULL,
  `psd6` tinyint(1) NOT NULL,
  `psd7` tinyint(1) NOT NULL,
  `psd8` tinyint(1) NOT NULL,
  `psd9` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `maxPlayers` (`maxPlayers`),
  KEY `p1_handLimit` (`p1`,`handLimit`),
  KEY `p2_handLimit` (`p2`,`handLimit`),
  KEY `p3_handLimit` (`p3`,`handLimit`),
  KEY `p4_handLimit` (`p4`,`handLimit`),
  KEY `p5_handLimit` (`p5`,`handLimit`),
  KEY `p6_handLimit` (`p6`,`handLimit`),
  KEY `p7_handLimit` (`p7`,`handLimit`),
  KEY `p8_handLimit` (`p8`,`handLimit`),
  KEY `p9_handLimit` (`p9`,`handLimit`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

Объяснение запроса:

+------+--------------+--------------------------+------+---------------+--------------+---------+-------+--------+----------------+
| id   | select_type  | table                    | type | possible_keys | key          | key_len | ref   | rows   | Extra          |
+------+--------------+--------------------------+------+---------------+--------------+---------+-------+--------+----------------+
|    1 | PRIMARY      | ps_hands                 | ref  | p1_handLimit  | p1_handLimit | 3       | const | 182239 | Using where    |
|    2 | UNION        | ps_hands                 | ref  | p2_handLimit  | p2_handLimit | 3       | const | 290077 | Using where    |
|    3 | UNION        | ps_hands                 | ref  | p3_handLimit  | p3_handLimit | 3       | const | 273151 | Using where    |
|    4 | UNION        | ps_hands                 | ref  | p4_handLimit  | p4_handLimit | 3       | const | 248191 | Using where    |
|    5 | UNION        | ps_hands                 | ref  | p5_handLimit  | p5_handLimit | 3       | const | 255685 | Using where    |
|    6 | UNION        | ps_hands                 | ref  | p6_handLimit  | p6_handLimit | 3       | const | 362813 | Using where    |
|    7 | UNION        | ps_hands                 | ref  | p7_handLimit  | p7_handLimit | 3       | const | 358672 | Using where    |
|    8 | UNION        | ps_hands                 | ref  | p8_handLimit  | p8_handLimit | 3       | const | 264515 | Using where    |
|    9 | UNION        | ps_hands                 | ref  | p9_handLimit  | p9_handLimit | 3       | const | 221512 | Using where    |
| NULL | UNION RESULT | <union1,2,3,4,5,6,7,8,9> | ALL  | NULL          | NULL         | NULL    | NULL  | NULL   | Using filesort |
+------+--------------+--------------------------+------+---------------+--------------+---------+-------+--------+----------------+

1 Ответ

0 голосов
/ 10 октября 2018

Как я уже сказал в комментарии, может помочь наличие индекса (или начиная с) поля date.Кроме того, поскольку вы, вероятно, не сможете воспользоваться индексом, включающим поля p#, вы можете попробовать версию запроса, отличную от UNION, такую ​​как

SELECT `id`, `currency`, `handLimit`, `date`
   , CASE 
     WHEN `p1` = '274606' THEN `pp1`
     WHEN `p2` = '274606' THEN `pp2`
     -- and so on ...
     END AS `profit`
   , CASE 
     WHEN `p1` = '274606' THEN `psd1`
     WHEN `p2` = '274606' THEN `psd2`
     -- and so on ...
     END AS AS `isSD` 
FROM `ps_hands` 
WHERE `date` BETWEEN '2018-10-01' AND '2018-10-10'
   AND '274606' IN (`p1`,`p2`,`p3`,`p4`,`p5`,`p6`,`p7`,`p8`,`p9`)
ORDER BY `id` ASC;

РЕДАКТИРОВАНИЕ / ПРЕДУПРЕЖДЕНИЕ: Если в одной и той же строке может быть более одного p # с одинаковым значением, вышеприведенное не будет работать;вместо этого необходимо скорректировать выражения для profit и isSD (возможно, сложив значения pp # вместе?) ... и вы все равно не получите отдельную строку результатов для каждого совпадения столбца.


Редактировать # 2: отдельные составные индексы (p#, date) или (date, p#) для каждого p # должны значительно помочь вашему исходному запросу.Сначала я бы попробовал только один индекс date, а если он недостаточно эффективен, воспользуйтесь составными индексами (date, p#).Для вашего запроса индексы (date, p#), вероятно, не будут работать намного лучше, чем индексы (p#, date), но они эффективно дадут вам индекс date, которым могут воспользоваться другие запросы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...