OR 运算符中的 MySQL 性能

标签 mysql indexing innodb

这是我的 table :

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-3ms,结果集1290行,表总行数1008700:

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 中遇到某种瓶颈,因为记录数已经超过一百万,并且会想知道其他可能的提高性能的策略。

最佳答案

有时 MySQL 无法优化 OR 查询。在这种情况下,您可以使用 UNION 将其拆分为两个查询:

SELECT * FROM relationship WHERE e_e_oid = @value1
UNION
SELECT * FROM relationship WHERE e_e_oid2 = @value2

每个子查询都会使用合适的索引,然后合并结果。

但是,在简单的情况下,MySQL 可以自动执行此转换,并且它会在您的查询中执行此操作。这就是 EXPLAIN 输出中的 Using union 的含义。

关于OR 运算符中的 MySQL 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40358169/

相关文章:

php - 我如何在mysql中显示段落?

mysql - 使用Select查询在mysql中创建更新脚本,语法问题?

如果存在具有 2 个特定列的行,则 MYSQL 更新表;如果不存在,则插入新行

MySQL 'Too many keys' 错误

mysql - AWS 上的 Socialengine 4.8.6(EC2、RDS (MYSQL/INNODB)、S3 和 CLOUDFRONT)- 启动时白屏/可能的 INNODB 问题

mysql - 为什么我的 MySQL 服务器无法识别外键关系?

mysql - 错误 2002 (HY000) : Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)

Python:在字符串中查找子字符串并返回子字符串的索引

logging - 如何查看在 Azure 上托管的数据库上执行的查询历史记录(全部或长期)?

mysql - 为什么IX锁与InnoDB中的另一个IX锁兼容?