为什么这个MySQL查询不使用完整索引?

为什么这个MySQL查询不使用完整索引?,mysql,query-optimization,Mysql,Query Optimization,你能帮我解答这个问题吗 SELECT p.patid, MAX(c1.eventdate) as eventdate from patient as p left join op_adv_effects._clinical as c1 on p.patid = c1.patid where c1.eventdate < p.case_index group by p.patid 解释以下内容: *************************** 1. row ********

你能帮我解答这个问题吗

SELECT p.patid, MAX(c1.eventdate) as eventdate 
from patient as p 
left join op_adv_effects._clinical as c1 on p.patid = c1.patid 
where c1.eventdate < p.case_index 
group by p.patid
解释以下内容:

*************************** 1. row ********************
           id: 1
  select_type: SIMPLE
        table: p
         type: index
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 7
          ref: NULL
         rows: 182939
        Extra: Using index
*************************** 2. row ********************
           id: 1
  select_type: SIMPLE
        table: c1
         type: ref
possible_keys: idx_clin_eventdate_medcode,idx_clin_eventdate_adid
          key: idx_clin_eventdate_medcode
      key_len: 4
          ref: gprd_opadveff_extra_elisa.p.patid
         rows: 171
        Extra: Using where; Using index
为什么它不使用idx_clin_eventdate_medcode的前两个字段,即patid、eventdate,而只使用patid see ref列

如果我将where条件更改为equality,它将正常工作:

SELECT p.patid, MAX(c1.eventdate) as eventdate 
from patient as p 
left join op_adv_effects._clinical as c1 on p.patid = c1.patid 
where c1.eventdate = p.case_index 
group by p.patid

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: p
         type: index
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 7
          ref: NULL
         rows: 182939
        Extra: Using index
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: c1
         type: ref
possible_keys: idx_clin_eventdate_medcode,idx_clin_eventdate_adid
          key: idx_clin_eventdate_medcode
      key_len: 7
          ref: gprd_opadveff_extra_elisa.p.patid,gprd_opadveff_extra_elisa.p.cas
e_index
         rows: 1
        Extra: Using index
对于某些建议的变化,结果相同:

explain SELECT  patid,
(SELECT  eventdate
FROM  op_adv_effects._clinical
WHERE  patid = p.patid
AND eventdate < p.case_index
ORDER BY  eventdate DESC
LIMIT  1 ) AS eventdate
FROM  patient AS p;

*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: p
         type: index
possible_keys: NULL
          key: PRIMARY
      key_len: 7
          ref: NULL
         rows: 182939
        Extra: Using index
*************************** 2. row ***************************
           id: 2
  select_type: DEPENDENT SUBQUERY
        table: _clinical
         type: ref
possible_keys: idx_clin_eventdate_medcode,idx_clin_eventdate_adid
          key: idx_clin_eventdate_medcode
      key_len: 4
          ref: gprd_opadveff_extra_elisa.p.patid
         rows: 171
        Extra: Using where; Using index; Using filesort


explain SELECT  patid, 
( SELECT  MAX(eventdate)
FROM  op_adv_effects._clinical
WHERE  patid = p.patid
AND  eventdate < p.case_index) AS eventdate
FROM  patient AS p;

*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: p
         type: index
possible_keys: NULL
          key: PRIMARY
      key_len: 7
          ref: NULL
         rows: 182939
        Extra: Using index
*************************** 2. row ***************************
           id: 2
  select_type: DEPENDENT SUBQUERY
        table: _clinical
         type: ref
possible_keys: idx_clin_eventdate_medcode,idx_clin_eventdate_adid
          key: idx_clin_eventdate_medcode
      key_len: 4
          ref: gprd_opadveff_extra_elisa.p.patid
         rows: 171
        Extra: Using where; Using index
该查询是更复杂的查询的一部分,如下所述。但是,这只是几个复杂查询的一个示例,这些查询都应该使用eventdate上缺少的索引部分。出于这个原因,这是相当重要的

CREATE TABLE bmi_lp
(PRIMARY KEY (patid))
ENGINE=INNODB DEFAULT CHARSET=latin1 COLLATE=latin1_general_cs
SELECT tmp.patid, a2.data3 as bmi_lp, tmp.eventdate as bmi_lp_date 
from ( 
SELECT p.patid, MAX(c.eventdate) as eventdate 
from patient as p 
left join op_adv_effects._clinical as c1 on p.patid = c1.patid 
left join op_adv_effects._additional as a1 on c1.patid = a1.patid 
where c1.adid <> 0 and c1.adid = a1.adid 
and a1.enttype = 13 
and a1.data3 is not null 
and c1.eventdate < p.case_index 
group by p.patid 
order by p.patid) as tmp 
left join op_adv_effects._clinical   as c2 on tmp.patid = c2.patid 
left join op_adv_effects._additional as a2 on c2.patid = a2.patid 
where tmp.eventdate = c2.eventdate and c2.adid = a2.adid
因为你现在正在做一个内部连接。你是有意的吗

不管怎么说,因为有“而不是”,请尝试一下:

SELECT  patid, 
      ( SELECT  MAX(eventdate)
            FROM  op_adv_effects._clinical
            WHERE  patid = p.patid
              AND  eventdate < p.case_index 
      ) AS eventdate
    FROM  patient AS p;

输出中有多少行?

请注意,此查询呈现为内部连接谢谢,这是我正在尝试改进的更复杂查询的一小部分,因为它非常慢。我尝试使用>而不是<作为实验,但它并不使用完整的索引。如果可能的话,我强烈建议升级到PostgreSQL,它处理复杂查询的效果会更好。在mysql中,通常最好保持查询尽可能简单。谢谢,现在不可能了。即使下面的简单查询也有相同的问题:选择p.patid,c1.eventdate from patient as p left join op_adv_effects.\u clinical as c1 on p.patid=c1.patid,其中c1.eventdate>p.case_indexas下面使用BETWEEN的查询也有相同的问题选择p.patid,c.eventdate从患者身上作为p左加入op_adv_effects.\u临床作为c on p.patid=c.patid,其中c.eventdate介于'01/01/1999'和'31/12/1999'之间。在这种情况下,您的选择是强制使用索引或添加order by,并希望mysql完成它的工作谢谢您,好的建议,但不幸的是没有改进。。我还尝试了选择patid,从op_adv_effects中选择MINeventdate。_clinical,其中patid=p.patid,eventdate>p.case_索引作为eventdate,患者作为p;六羟甲基三聚氰胺六甲醚。。。你能解释一下这些问题吗?包括我发布的新版本,我在问题末尾添加了解释。感谢输出中的行数超过173000无论是否使用完整索引,返回173K行都需要时间。多长时间innodb\u buffer\u pool\u size的值是多少?查询是CPU绑定还是I/O绑定?
CREATE INDEX idx_clin_eventdate_medcode ON _clinical (patid ASC, eventdate DESC);
SELECT  patid, 
      ( SELECT  MAX(eventdate)
            FROM  op_adv_effects._clinical
            WHERE  patid = p.patid
              AND  eventdate < p.case_index 
      ) AS eventdate
    FROM  patient AS p;
SELECT  patid, 
      ( SELECT  eventdate
            FROM  op_adv_effects._clinical
            WHERE  patid = p.patid
              AND  eventdate < p.case_index
            ORDER BY  eventdate DESC
            LIMIT  1 
      ) AS eventdate
    FROM  patient AS p;