索引提示和查询执行计划如何工作?

时间:2012-01-01 11:17:47

标签: mysql optimization

我正在运行一系列测试以确定忽略索引如何影响我的查询速度。以下是第一个测试系列的查询字符串:

SELECT P.pid, P.name, P.cty, P.fla, P.pos, P.lvl, P.akP * E.usD AS 'ask'
 FROM Pig P
 IGNORE INDEX FOR JOIN (id_fla) // index is on fla (MEDIUMINT) column
 INNER JOIN Eel E ON E.cur = P.cur
 WHERE P.status IN ('a', 'l') AND P.fla >107 AND P.cDate >CURDATE() AND P.pos <45
 HAVING ask BETWEEN '50' AND '500'
 ORDER BY fla DESC
 LIMIT 100;

在第二个测试系列中,IGNORE INDEX FOR JOIN 将替换为IGNORE INDEX FOR ORDER BY 。在第3个测试系列中,IGNORE INDEX FOR ORDER BY替换为IGNORE INDEX FOR GROUP BY

以下是测试结果和相应的查询执行计划。

测试1(加入IGNORE索引):

Query Number (n): 1    2    3    4    5    6    7    8    9    10
Query Times (s):  90.6 0.13 27.2 21.4 0.11 0.10 29.8 27.8 0.17 6.56
Rows Examined (k):26   26   36   43   37   37   58   85   66   98

测试2(订购时的IGNORE索引):

Query Number (n): 1    2    3    4    5    6    7    8    9    10
Query Times (s):  90.7 0.14 26.5 21.2 0.10 0.11 35.0 28.5 0.17 6.64
Rows Examined (k):26   26   36   43   37   37   58   85   66   98

测试3(IGNORE INDEX FOR GROUP BY):

Query Number (n): 1    2    3    4    5    6    7    8    9    10
Query Times (s):  263  10.1 10.1 9.95 9.94 10.1 10.0 9.95 9.96 10.1
Rows Examined (M):4.18 4.18 4.18 4.18 4.18 4.18 4.18 4.18 4.18 4.18
  • 注1:s - 秒,k - 千,M - 百万
  • 注意2:pos是查询之间唯一不同的WHERE条件 {1}}条件之间的WHERE条件完全相同 每个查询号的三个测试。

测试1(加入IGNORE索引):

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: P
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 5000014
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: E
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 3
          ref: BS.P.cur
         rows: 1
        Extra: 

测试2(订购的IGNORE索引)和测试3(IGNORE INDEX for GROUP BY):

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: P
         type: range
possible_keys: id_flA
          key: id_flA
      key_len: 3
          ref: NULL
         rows: 4223660
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: E
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 3
          ref: BS.P.cur
         rows: 1
        Extra: 

尽管测试2和测试3的查询执行计划与测试1相同且不同,但实际查询速度和检查的行似乎将测试1和2组合在一起。所以我有两个问题需要问:

  1. 在这种情况下Index Hint如何工作?
  2. 表扫描似乎是在测试3上进行的,但索引显示为 使用。 MySQL是否遵循了查询执行计划 EXPLAIN SELECT声明?

1 个答案:

答案 0 :(得分:0)

   WHERE 
          P.status IN ('a', 'l') 
      AND P.fla > 107 
      AND P.cDate > CURDATE() 
      AND P.pos < 45
   HAVING 
      ask BETWEEN '50' AND '500'

您的查询本身看起来很好(只是澄清帖子中的格式)。但是,如果您拥有的唯一索引是fla,那就是一个问题。索引应该基于您的查询条件所基于的...尝试更多地关注应该获得最小粒度的常见查询条件以帮助优化...我不知道哪个会更好...基于状态,或者基于cDate的条目,然后你的fla和pos列的位置。例如,如果你有400万个条目,500k是状态“a”,400k是状态“l”,但只有20k有cDate&gt; curdate(),这将是你的索引的起点... CDate上的索引...然后添加下一级别的粒度。如果您有15个不同的状态代码,那么该cDate段中的每个状态有多少?但是你比S / O的任何人都更了解你的数据,但我会为索引提出这个建议。

索引(状态,cdate,fla,pos)并尝试,然后另一个索引(cdate,status,fla,pos),看看哪个有助于你的表现。 107中有多少“fla”值存在?如果它的数量很小,那么可能会把它作为你的第一个索引限定符,但我怀疑它是因为你试图不利用那个。

祝你好运,希望这可以帮助您更多地考虑您的数据。