ОБНОВЛЕНИЕ
Я сделал так, чтобы мои запросы и схема точно соответствовали вашему исходному вопросу, ключу из нескольких столбцов и всем.Единственное возможное отличие состоит в том, что я заполнил каждую таблицу двумя миллионами записей.Мой запрос (ваш запрос) выполняется за 0,15 секунды.
delimiter $$
set @userid = 6
$$
SELECT
tbladdeditem.addeditemid, tblprivateitem.iitemid, tblprivateitem.itemid
FROM tbladdeditem
INNER JOIN tblprivateitem
ON tblprivateitem.itemid=tbladdeditem.itemid
AND (tblprivateitem.userid=@userid or tblprivateitem.userid = 1)
WHERE tbladdeditem.userid=@userid
У меня есть то же объяснение, что и вы, и с моими данными мой запрос возвращает более тысячи совпадений без каких-либо проблем.Быть в полном недоумении, поскольку у вас действительно не должно быть этих проблем - возможно ли, что вы используете очень ограниченную версию MySQL?Вы работаете в 64-битной версии?Достаточно памяти?
Я сделал предположение, что ваш запрос не работает должным образом, а когда мой был, предположил, что я исправил вашу проблему.Так что теперь я ем ворону.Я опубликую некоторые из проспектов, которые я пошел вниз.Но я говорю вам, ваш запрос, как вы разместили его изначально, работает просто отлично.Я могу только представить, что ваш MySQL побежал на жесткий диск или что-то.Извините, я не мог больше помочь.
ПРЕДЫДУЩИЙ ОТВЕТ (который также является обновлением)
Я сломал и воссоздал вашу проблему в моей собственной базе данных.После попытки независимых индексов в userid
и itemid
мне не удалось получить запрос ниже нескольких секунд, поэтому я настроил очень специфические ключи из нескольких столбцов, как указано в запросе.Обратите внимание, что tbladdeditem
запрос с несколькими столбцами начинается с itemid
, а на tblprivateitem
столбцы меняются местами:
Вот схема, которую я использовал:
CREATE TABLE `tbladdeditem` (
`addeditemid` int(11) NOT NULL AUTO_INCREMENT,
`itemid` int(11) NOT NULL,
`userid` mediumint(9) NOT NULL,
PRIMARY KEY (`addeditemid`),
KEY `userid` (`userid`),
KEY `i_and_u` (`itemid`,`userid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `tblprivateitem` (
`privateitemid` int(11) NOT NULL AUTO_INCREMENT,
`userid` mediumint(9) NOT NULL DEFAULT '1',
`itemid` int(10) NOT NULL,
`iitemid` mediumint(9) NOT NULL,
PRIMARY KEY (`privateitemid`),
KEY `userid` (`userid`),
KEY `itemid` (`itemid`),
KEY `u_and_i` (`userid`,`itemid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Я заполнилкаждая таблица с 2 миллионами записей случайных данных.Я сделал несколько предположений:
- userid варьируется от 1 до 2000
- itemid варьируется от 1 до 10000
Это дает каждому пользователю около тысячи записей вкаждая таблица.
Вот две версии запроса (я использую верстак для своего редактора):
Версия 1 - выполнить всю фильтрацию при объединении.
Результат: 0,016 секунды, чтобы вернуть 1297 строк
delimiter $$
set @userid = 3
$$
SELECT
a.addeditemid,
p.iitemid,
p.itemid
FROM tblprivateitem as p
INNER JOIN tbladdeditem as a
ON (p.userid in (1, @userid))
AND p.itemid = a.itemid
AND a.userid = @userid
$$
Вот объяснение:
EXPLAIN:
id select_type table type key ref rows extra
1 SIMPLE p range u_and_i 2150 Using where; Using index
1 SIMPLE a ref i_and_u 1 Using where; Using index
Версия 2 - предварительная фильтрация
Результат: 0,015 секунды, чтобы вернуть 1297 строк
delimiter $$
set @userid = 3
$$
SELECT
a.addeditemid,
p.iitemid,
p.itemid
from
(select userid, itemid, iitemid from tblprivateitem
where userid in (1, @userid)) as p
join tbladdeditem as a on p.userid = a.userid and a.itemid = p.itemid;
where a.userid = @userid
$$
Вот объяснение:
id select_type table type key ref rows extra
1 PRIMARY <derived2> ALL null null 2152
1 PRIMARY a ref i_and_u p.itemid,const 1 Using where; Using index
2 DERIVED p1 range u_and_i 2150 Using where