Оптимизация запросов - PullRequest
2 голосов
/ 15 января 2011
SELECT nar.name, nar.reg, stat.lvl
FROM members AS nar
JOIN stats AS stat 
ON stat.id = nar.id
WHERE nar.ref = 9

У меня есть индексы для идентификатора в обеих таблицах, и у меня также есть индекс referavo. Но, тем не менее, он проверяет все строки в таблице статистики (я использую объяснение, чтобы получить эту информацию), но в таблице членов он проверяет только одну строку, как это должно быть. Что не так с таблицей статистики? Большое спасибо.

CREATE TABLE `members` (
 `id` int(11) NOT NULL
 `ref` int(11) NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT


CREATE TABLE `stats` (
 `id` int(11) NOT NULL AUTO_INCREMENT
 PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC



id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE stat ALL PRIMARY NULL NULL NULL 22  
1 SIMPLE nar eq_ref PRIMARY PRIMARY 4 table_nme.stat.id 1 Using where

Ответы [ 2 ]

4 голосов
/ 15 января 2011

Ваши таблицы смехотворно маленькие - всего 23 строки - это крошечный .

MySQL выбирает разные планы запросов в зависимости от того, сколько строк в таблице и сколько оценок будет выбрано (из статистики). Вы должны тестировать производительность ваших запросов с реалистичными данными - и объем данных, и распределение значений в данных должны быть максимально реалистичными. В противном случае план запроса, выбранный MySQL при тестировании, может отличаться от фактического плана запроса для вашей действующей системы.

Ваши таблицы настолько малы, что использование индекса может быть на медленнее , чем просто проверка таблицы напрямую. Помните, что проверка данных, которые уже находятся в памяти, выполняется быстро, но чтение выполняется медленно. Для доступа к индексу может потребоваться дополнительное чтение - сначала индекс должен быть выбран и прочитан, чтобы найти, какие строки выбрать, затем, если ваш индекс не является индексом покрытия, соответствующие строки в таблице должны быть выбраны и прочитаны, чтобы получить значения, которых нет в индексе. MySQL имеет полное право не использовать индекс, даже если он доступен, если считает, что это приведет к более медленному плану.

Поместите еще несколько строк в вашу таблицу (тысячи) и попробуйте снова запустить EXPLAIN. Вероятно, вы обнаружите, что при наличии большего количества строк индекс PRIMARY KEY будет использоваться для объединения.

1 голос
/ 15 января 2011

MySQL может использовать только один индекс за одну таблицу, поэтому он видит строку member, используя индекс, а затем выполняет последовательный поиск идентификатора.

Вы должны создать индекс из нескольких столбцов для таблицы members

 CREATE INDEX idref ON members(id,ref);

Пожалуйста, попробуйте и обратный вариант, если он не улучшится (сначала: удалите index idref для участников)

 CREATE INDEX idref ON members(ref,id);

(я не могу попробовать сам сейчас)

...