【问题标题】:Simple Select Statement on MySQL Database HangingMySQL 数据库挂起的简单 Select 语句
【发布时间】:2010-06-17 16:20:48
【问题描述】:

我在一个 very 大表上有一个 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 都被索引为 BTree,但没有前缀 - 整个列都被索引。州列是 2 个字母的州代码。

我的发现是这样的:

  1. 当@name = 'John Smith' 和@state = '%' 时,搜索速度非常快,并且会立即产生结果。
  2. 当 @name = 'John Smith' 和 @state = 'FL' 时,搜索需要 5 分钟(通常这意味着 Web 服务超时...)
  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 分钟。

现在,重申一下 - 表格未标准化。与许多其他用户一样,John Smith 出现了很多次,因为没有引用某种形式的用户/人员表。我不确定单个用户可能出现多少次,但表本身有 9000 万条记录。再说一次,不是我的设计……

我想知道的是——虽然这个设计有很多问题,但是是什么导致了这个特定的问题。

我的猜测是索引树太大了,遍历它们需要很长时间。 (名、姓、全名)

无论如何,我感谢任何人对此的帮助。就像我说的,我正在努力说服他们重新设计,但与此同时,如果有人能帮我找出确切的问题是什么,那就太好了。

更新

根据要求,以下是运行解释后的详细信息:

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'

【问题讨论】:

  • 建议您使用 EXPLAIN 查看查询计划。将这些查询的 EXPLAIN 结果添加到您的问题中会非常有用。 INDEX 结构并不是 100% 清楚的。还请包括SHOW CREATE TABLE Activity\G的输出
  • 拥有 9000 万条记录,如果像您说的那样每列都有很多点击量,那么您的时间可能会花在一遍又一遍地合并所有结果上,就像其他人所说的那样,EXPLAIN 是你的朋友

标签: sql mysql indexing


【解决方案1】:

我们需要知道表是如何定义的,所以给我们结果

显示创建表活动

会有帮助的。

从它的声音来看,State 列有一些东西 - 它是否被索引?

另一个很好的工具是 EXPLAIN 命令。

使用

解释 选择 名字、姓氏、全名、州 从活动 哪里(名字='约翰史密斯' 或姓氏='约翰史密斯' 或全名='约翰·史密斯') 和状态='FL';

并将结果与​​查询的其他变体的 EXPLAIN 输出进行比较。

【讨论】:

    【解决方案2】:

    只是猜测没有看到你的执行计划,但你可以尝试创建复合索引

    (FirstName, State)
    (LastName, State)
    (FullName, State)
    

    甚至是单个复合索引:

    (State, FirstName, LastName, FullName)
    

    【讨论】:

      【解决方案3】:

      我认为您需要花一些时间来处理EXPLAIN statement。 Peter Lang 可能是正确的,您需要一些复杂的索引,但 EXPLAIN 将显示任何类似的更改所产生的影响比试错法要好得多。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多