MySQL数据库挂起的简单选择语句

时间:2010-06-17 16:20:48

标签: sql mysql indexing

我在 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个字母的州代码。

我发现的是:

  1. 当@name ='John Smith'和@state ='%'时,搜索速度非常快,并立即产生结果。
  2. 当@name ='John Smith'和@state ='FL'时,搜索需要5分钟(通常这意味着网络服务超时......)
  3. 当我删除FirstName和LastName比较,并且只使用FullName和State时,上述两种情况都非常快。
  4. 当我替换FirstName,LastName,FullName和State搜索,但是对每次搜索使用LIKE时,它对@ name ='John Smith%'和@state ='%'的速度很快,但@ name ='的速度很慢John Smith%'和@ state ='FL'
  5. 当我搜索'John Sm%'和@ state ='FL'时,搜索会立即找到结果
  6. 当我搜索'John Smi%'和@ state ='FL'时,搜索需要5分钟。
  7. 现在,重申一下 - 该表未正常化。 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'
    

3 个答案:

答案 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)

我认为你需要花一些时间来处理EXPLAIN statement。 Peter Lang可能你需要一些复杂的索引,但是EXPLAIN会显示出任何类似的变化会比试错更好。

哦,并在您尝试配置的任何select语句中使用keyword SQL_NO_CACHE,以防止查询缓存改变您的结果(只需在SELECT之后添加)