以下是三个MySQL查询.第一个返回我在一个查询中寻找的所有内容,而后两个返回相同的聚合结果,但在两个查询中.
我想知道为什么单个查询运行时间要长2-100倍,而且似乎所有三个查询之间的处理时间应相等.有没有办法优化单个查询以便像单个查询一样快速运行?在单个查询的WHERE语句中添加更多OR不会增加处理时间,但我有需要执行更多OR的情况,并且最终单个查询将与运行十个单独查询一样快.
单个查询似乎也会在运行后缓存,并且第一次运行可能需要几分钟,而单个查询始终在同一时间范围内完成.
多列索引会在这里产生很大的不同吗?
值得注意的是,该表没有ID字段作为主索引.这会导致这种不良行为吗?
在这里运行测试很困难,因为表有一亿行,并且添加列和索引需要接近一天.
单一查询(4.2s)
SELECT name_id
FROM staging_company_search
WHERE
(name_word_0 = 'the' AND name_word_1 = 'glazier')
OR (name_word_0 = 'bridgewaters' AND name_word_1 = '');
Run Code Online (Sandbox Code Playgroud)
等价的集合查询(每个0.8秒)
SELECT name_id
FROM staging_company_search
WHERE name_word_0 = 'the' AND name_word_1 = 'glazier';
SELECT name_id
FROM staging_company_search
WHERE name_word_0 = 'bridgewaters' AND name_word_1 = '';
Run Code Online (Sandbox Code Playgroud)
解释这些问题
id select_type table type possible_keys key key_len ref rows extra
1 SIMPLE staging_company_search range name_word_0,name_word_1 name_word_0 102 NULL 2197605 Using index condition; Using where
1 SIMPLE staging_company_search ref name_word_0,name_word_1 name_word_1 102 const 128 Using index condition; Using where
1 SIMPLE staging_company_search ref name_word_0,name_word_1 name_word_0 102 const 33 Using index condition; Using where
Run Code Online (Sandbox Code Playgroud)
数据库模式
CREATE TABLE `staging_company_search` (
`name_id` int(11) unsigned NOT NULL DEFAULT '0',
`name_word_0` varchar(100) NOT NULL,
`name_word_1` varchar(100) NOT NULL,
KEY `name_id` (`name_id`),
KEY `name_word_0` (`name_word_0`),
KEY `name_word_1` (`name_word_1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Run Code Online (Sandbox Code Playgroud)
这是因为mysql只使用一个索引来进行简单的查询。
如果在多个索引之间进行选择,MySQL通常会使用找到最少行数的索引(最具选择性的索引)。
然而,从5.0版本开始,mysql可以并且将会通过 索引合并优化来使用两个索引。不幸的是,这种情况并不总是发生,即使发生,结果也不是那么好。
第一个解释输出显示在带有 OR 子句的查询中未使用索引合并优化。它仅使用索引name_word_0
name_word_0 非常适合WHERE name_word_0 = 'the' AND name_word_1 = 'glazier';,但正如第三个解释的输出所示,它根本不适合WHERE name_word_0 = 'bridgewaters' AND name_word_1 = '';
因此组合查询确实很慢。您可以通过创建跨越 name_word_0 和 name_word_1 的复合索引来克服这个问题。我注意到你的钥匙透镜很长。您可以创建部分索引,并且可能会进一步加快速度。
CREATE INDEX word01 ON staging_company_search (name_word_0(20), name_word_1(20))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
70 次 |
| 最近记录: |