#mysql #wordpress #indexing #entity-attribute-value
Вопрос:
Это мой столик:
CREATE TABLE `e_relationship` (
`OID` int(11) NOT NULL AUTO_INCREMENT,
`E_E_OID` int(11) NOT NULL,
`E_E_OID2` int(11) NOT NULL,
`REL_DISPLAY` text NOT NULL,
`APP_OID` int(11) NOT NULL,
`META_OID` int(11) NOT NULL,
`STORE_DATE` datetime NOT NULL,
`UID` int(11) DEFAULT NULL,
PRIMARY KEY (`OID`),
KEY `Left_Entity` (`E_E_OID`),
KEY `Right_Entity` (`E_E_OID2`),
KEY `Meta_Left` (`META_OID`,`E_E_OID`),
KEY `Meta_Right` (`META_OID`,`E_E_OID2`)
) ENGINE=InnoDB AUTO_INCREMENT=310169 DEFAULT CHARSET=utf8;
Следующий запрос занимает около 2,5-3 мс, результирующий набор составляет 1290 строк, а общее количество строк в таблице составляет 1 008 700.:
SELECT * FROM e_relationship WHERE e_e_oid=@value1 OR e_e_oid2=@value1
Это результат EXPLAIN
:
id: 1
select_type: SIMPLE
table: e_relationship
type: index_merge
possible_keys: Left_Entity,Right_Entity
key: Left_Entity,Right_Entity
key_len: 4,4
ref: NULL
rows: 1290
Extra: Using union(Left_Entity,Right_Entity); Using where
Я хотел бы ускорить этот запрос, так как это очень важно в моей системе, я не уверен, что достиг какого-то узкого места в mysql, так как количество записей уже перевалило за миллион, и хотел бы знать о других возможных стратегиях для повышения производительности.
Комментарии:
1. 2,5-3 мс кажется более чем разумным, учитывая количество строк и распределение данных.
2. вы можете попробовать В операторе.
3. Во-первых (и, как заявил Михай), 3 мс-довольно хорошее время отклика для таблицы записей объемом 1 млн. Во-вторых, попробуйте отслеживать СИСТЕМУ (процессор, ПАМЯТЬ, ДИСК) и посмотреть, достигает ли какой-либо из них высокого процента.
4. Согласно объяснению, MySQL уже использует оптимизацию слияния индексов для вашего запроса, это так быстро, как вы можете сделать без использования явного объединения. Вы сказали в комментарии к удаленному ответу, что объединение происходило медленнее. Это все, что вы можете получить как разработчик. С этого момента передайте задачу администратору базы данных, который может настроить параметры MySQL для повышения производительности запроса. Тем не менее, я склонен согласиться с мнением, что 2-3 мс кажутся достаточно быстрой производительностью.
5. Ваш запрос и так оптимизирован, и 3 мс-хороший результат. Если вам не нужны все столбцы и добавить индекс покрытия, вы можете сохранить таблицу поиска (чтобы испытать его, попробуйте
select id from
вместоselect * from
), но в остальном, это зависит от внешних факторов: как вы называете ваш запрос (например, использовать подготовленные операторы в PHP), сколько/какие другие запросы, и вашу общую производительность базы данных (так что в основном: сервер цене). Оценка: Для 1 м строк (еслиtext
столбец не слишком велик) ваш запрос, выполняемый непосредственно в MySQL на простаивающем (наполовину недавнем) процессоре с достаточным объемом оперативной памяти, не должен показывать ничего, кроме 0,000 сек.
Ответ №1:
Иногда у MySQL возникают проблемы с оптимизацией OR
запросов. В этом случае вы можете разделить его на два запроса, используя UNION
:
SELECT * FROM relationship WHERE e_e_oid = @value1
UNION
SELECT * FROM relationship WHERE e_e_oid2 = @value2
Каждый подзапрос будет использовать соответствующий индекс, а затем результаты будут объединены.
Однако в простых случаях MySQL может автоматически выполнить это преобразование, и он делает это в вашем запросе. Вот что Using union
EXPLAIN
означает вывод.
Комментарии:
1. Это занимает еще больше времени
Ответ №2:
Есть столик E_E_OIDs
. В нем будет (до) 2 строки на каждую e_relationship
. Затем
SELECT ...
FROM eeoids AS ee
JOIN e_relationship AS er ON er.ooid = ee.oid
И измените с 2 столбцов на один. И избавьтесь от 2 индексов.
Оказывает ли эффект ИЛИ даже быстрее, чем UNION
.
(Остальные подробности оставлены читателю.)
Аналогия
Предположим, у человека есть несколько телефонных номеров (стационарный, мобильный, рабочий и т. Д.), И я хочу просмотреть его запись на основе одного телефонного номера. Итак, я строю таблицу phone
: personID
пар и индексирую ее phone
. Тогда я делаю
SELECT ...
FROM Phones AS nums
JOIN Persons AS x ON x.personID = nums.personID
WHERE nums.phone = '123-555-1212'
Примечание: В таблице нет номера телефона Persons
.
Твое E_E_OID
похоже на мое phone
.
Комментарии:
1. Не будет ли объединение контрпродуктивным?
2.
JOIN
вероятно , будет меньше накладных расходов, чемOR
илиUNION
илиindex merge
.3. Но
JOIN
это не замена, а дополнение, конечно, мне все еще нужноOR
иindex merge
наE_E_OIDs
столе4. Вы ищете один OID? Или два?
5. Мне нужно отфильтровать
E_E_OID
иE_E_OID2