在查询中使用if条件时的全表扫描

时间:2012-09-11 09:24:55

标签: mysql database

我遇到的情况是在查询的where子句中使用if条件。所有字段都有自己的indexes,用于if。但查询进行了完整的table扫描。 任何人都可以帮我避免全表扫描吗?

我的查询:

EXPLAIN SELECT COUNT(*) 
FROM BILL_PATIENT_BILL AS fetchInfo 
WHERE IF(fetchInfo.BILL_TYPE='OP' 
AND fetchInfo.BILL_CATEGORY=0,fetchInfo.DUE_AMOUNT != 0,TRUE)

1 个答案:

答案 0 :(得分:1)

EXPLAIN SELECT COUNT(*) 
FROM BILL_PATIENT_BILL AS fetchInfo 
WHERE IF(fetchInfo.BILL_TYPE='OP' 
AND fetchInfo.BILL_CATEGORY=0,fetchInfo.DUE_AMOUNT != 0,TRUE)

你的IF没有任何意义。它的作用是:

  • 如果BILL_TYPE ='OP',
  • 和BILL_CATEGORY = 0,
  • 然后当DUE_AMOUNT!= 0
  • 时,where子句将为true
  • 否则where子句始终为true。

但无论如何,你不需要它。您可以使用De Morgan

重写这样的查询
EXPLAIN SELECT COUNT(*) 
FROM BILL_PATIENT_BILL AS fetchInfo 
WHERE (fetchInfo.BILL_TYPE='OP' 
  AND fetchInfo.BILL_CATEGORY=0 
  AND fetchInfo.DUE_AMOUNT != 0)
  OR fetchInfo.BILL_TYPE<>'OP'
  OR fetchInfo.BILL_CATEGORY=0

你应该有一个索引(BILL_TYPE,BILL_CATEGORY,DUE_AMOUNT),但即使这样,使用OR子句,它仍然可能决定不使用索引。如果是这种情况,请尝试重写为联合:

SELECT COUNT(*) 
    FROM BILL_PATIENT_BILL AS fetchInfo 
    WHERE (fetchInfo.BILL_TYPE='OP' 
      AND fetchInfo.BILL_CATEGORY=0 
      AND fetchInfo.DUE_AMOUNT != 0)
UNION ALL
SELECT COUNT(*)
    FROM BILL_PATIENT_BILL AS fetchInfo 
      WHERE fetchInfo.BILL_TYPE<>'OP'
UNION ALL
SELECT COUNT(*)
    FROM BILL_PATIENT_BILL AS fetchInfo 
      WHERE fetchInfo.BILL_CATEGORY=0

您可以执行SUM来添加它们。

由于您实际上正在接受列的所有值,因此您甚至可能不需要where子句...

EXPLAIN SELECT COUNT(
  IF(fetchInfo.BILL_TYPE='OP' 
    AND fetchInfo.BILL_CATEGORY=0 
    AND fetchInfo.DUE_AMOUNT != 0,
  1,
  0)) 
FROM BILL_PATIENT_BILL AS fetchInfo