Почему этот запрос к таблице MEMORY медленнее, чем его аналог на InnoDB? - PullRequest
2 голосов
/ 11 февраля 2011

У меня есть версия таблицы InnoDB и MEMORY.Оба имеют одинаковые индексы и одинаковые 30000 строк данных.Есть конкретный запрос, который выполняется очень медленно, когда выполняется для таблицы MEMORY.

Вот против InnoDB:

SELECT emails.id
FROM emails
LEFT JOIN custom_data_person pd1 ON (pd1.person_id = emails.person_id)
WHERE pd1.field_id = 13

2928 rows in set (0.24 sec)

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: pd1
         type: ref
possible_keys: person_id,field_id
          key: field_id
      key_len: 5
          ref: const
         rows: 20240
        Extra: Using where; Using index
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: emails
         type: ref
possible_keys: person_id
          key: person_id
      key_len: 4
          ref: test.pd1.person_id
         rows: 1
        Extra: Using index

Вот MEMORY:

SELECT emails.id
FROM emails_memory AS emails
LEFT JOIN custom_data_person pd1 ON (pd1.person_id = emails.person_id)
WHERE pd1.field_id = 13

2928 rows in set (1.40 sec)

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: emails
         type: ALL
possible_keys: person_id
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 30000
        Extra: 
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: pd1
         type: ref
possible_keys: person_id,field_id
          key: person_id
      key_len: 10
          ref: test.emails.person_id,const
         rows: 1
        Extra: Using where; Using index

(Обратите вниманиеИндекс person_id является индексом BTREE. Я пытался сделать то же самое с индексом HASH по умолчанию, и результаты были такими же.)

Так что, похоже, MySQL оптимизировал второй запрос другим способом, что ухудшило его производительность.Это почему?Могу ли я это "исправить"?

1 Ответ

2 голосов
/ 11 февраля 2011

Тебе все равно.С крошечной таблицей с 30000 строк все будет очень быстро, даже сканирование таблицы.

Однако, похоже, что выбран другой план объяснения.В случае innodb сначала используется таблица custom_data_person, а также индекс покрытия.Затем он запрашивает таблицу адресов электронной почты для каждой строки, найденной в таблице custom_data_person.Это похоже на разумный план объяснения.

Возможно, в оптимизаторе таблиц памяти есть какая-то плохая пессимизация.

Я бы держался подальше от таблиц памяти.Если вам нужна таблица, которая ведет себя почти как таблица памяти, используйте таблицу MyISAM и обрежьте ее при запуске сервера.Таблицы памяти сосут невероятно плохо, потому что они хранят varchars, заполненные до максимальной длины, поэтому они обычно используют намного больше памяти, чем таблицы другого типа.MyISAM использует хранилище очень эффективно.В качестве альтернативы, используйте таблицы InnoDB для всего.

К сожалению, innodb не предоставляет способ установить долговечность для каждой таблицы, поэтому, если fsync в каждой транзакции вас беспокоит, вам придется делать больше (и, следовательно,меньшее количество транзакций.

Использование нескольких механизмов является компромиссом, поскольку сервер редко может каким-либо образом автоматически разделить свой (конечный) ОЗУ между механизмами.Таким образом, вы обычно хотите использовать только один движок;это включает в себя механизм памяти, который с радостью отнимет кучу памяти у вашего innodb (следовательно, сделает его медленнее, поскольку он может уместить меньше вашей базы данных в памяти), если вы настроите его таким образом.действительно, действительно не волнует 30 тысяч строк.30 тыс. Строк могут уместиться в самой маленькой памяти, даже если они огромны.Любой движок - это движок памяти, когда вы используете 30k строк.

...