我在 very 大表上有一个非常简单的sql select语句,它是非规范化的。 (根本不是我的设计,我只是试图优化,同时试图说服业主重新设计)
基本上,声明是这样的:
SELECT FirstName, LastName, FullName, State
FROM Activity
WHERE (FirstName=@name OR LastName=@name OR FullName=@name)
AND State=@state;
现在,FirstName,LastName,FullName和State都被索引为BTrees,但没有前缀 - 整个列都被编入索引。 State列是一个2个字母的州代码。
我发现的是:
现在,重申一下 - 该表未正常化。 John Smith和许多其他用户一样多次出现,因为没有提及某种形式的用户/人员表。我不确定单个用户可能出现多少次,但该表本身有9000万条记录。再次,不是我的设计...
我想知道的是 - 尽管此设计存在许多问题,但导致此特定问题的原因是什么。
我的猜测是索引树太大了,只需要花很长时间遍历它们。 (FirstName,LastName,FullName)
无论如何,我感谢任何人的帮助。就像我说的那样,我正在努力说服他们进行重新设计,但与此同时,如果有人能帮我弄清楚究竟是什么问题,那就太棒了。
更新
根据要求,以下是运行说明后的详细信息:
id: 1, select type: 'SIMPLE', table: 'activity', type: 'ref', possible keys: 'IDX_LastName,IDX_FirstName,IDX_FullName,IDX_State', key: 'IDX_State', key_len: '3', ref: 'const', rows: 7227364, extra: 'Using where'
答案 0 :(得分:2)
我们需要知道如何定义表,所以给我们
的结果show create table Activity
会有所帮助。
从它的声音来看,有一些关于State列的内容 - 是否已编入索引?
另一个好工具是EXPLAIN命令。
使用
EXPLAIN SELECT FirstName, LastName, FullName, State FROM Activity Where (FirstName='John Smith' OR LastName='John Smith' OR FullName='John Smith') AND State='FL';
并将结果与查询的其他变体的EXPLAIN输出进行比较。
答案 1 :(得分:1)
只是在没有看到执行计划的情况下猜测,但您可以尝试创建复合索引
(FirstName, State)
(LastName, State)
(FullName, State)
甚至是单个复合指数:
(State, FirstName, LastName, FullName)
答案 2 :(得分:0)