개발 전 SQL 코드에서는 where 조건이 업데이트된 쿼리도 여러 번 있었습니다. 다음은 or 사용의 단점과 이를 개선하는 방법을 보여주는 예입니다.
select f_crm_id from d_dbname1.t_tbname1 where f_xxx_id = 926067 and (f_mobile ='1234567891' or f_phone ='1234567891' ) limit 1
f_mobile과 f_phone 필드 모두 전화번호를 저장할 수 있다는 것을 쿼리문에서 쉽게 알 수 있습니다. 일반적인 아이디어는 이를 SQL로 사용하거나 해결하는 것이지만, 많은 양의 테이블 데이터는 단순히 재해:
t_tbanme1에는 idx_id_mobile(f_xxx_id,f_mobile), idx_phone(f_phone), idx_id_email(f_id,f_email) 인덱스가 있지만 설명 결과는 idx_id_email 인덱스를 사용합니다. . 때로는 운이 좋게도 idx_id_mobile f_xxx_id
를 사용할 수 있습니다. 왜냐하면 mysql의 각 쿼리에 대해 각 테이블에서 하나의 인덱스만 선택할 수 있기 때문입니다. idx_id_mobile 인덱스를 사용했는데 제한이 1이어서 데이터가 한 개만 있는 경우에는 빨리 결과를 얻을 수 있기를 바랍니다. 그러나 f_mobile에 대한 데이터가 없으면 f_phone 필드는 아래에서 하나씩만 검색할 수 있습니다. f_id 조건, 120,000개의 행을 스캔합니다. 또는 and와는 다릅니다. (f_xxx_id,f_mobile,f_phone)을 추가하면 피가 토할 것 같다고 생각하는 개발자도 있습니다~
따라서 SQL 최적화는 매우 간단합니다(f_mobile 및 f_phone에 해당 인덱스가 있어야 함), 방법 1:
(select f_crm_id from d_dbname1.t_tbname1 where f_xxx_id = 926067 and f_mobile ='1234567891' limit 1 ) UNION ALL (select f_crm_id from d_dbname1.t_tbname1 where f_xxx_id = 926067 and f_phone ='1234567891' limit 1 )
두 개의 독립적인 SQL이 인덱스를 사용할 수 있으며 각 쿼리에는 자체 제한이 있습니다. 두 결과 집합이 모두 반환되면 하나만 선택하세요.
이런 쿼리가 특히 자주 발생하는 경우(그리고 캐시가 없는 경우) 별도의 SQL 실행으로 변경하는 방법도 있습니다. 예를 들어 대부분의 숫자 값이 켜져 있습니다. f_mobile을 실행한 후 sql1을 먼저 실행하면 결과가 나올 것이고, 결과가 없다고 판단한 후 sql2를 실행하면 데이터베이스 쿼리 속도가 느려지고 코드에서 더 많은 작업을 처리할 수 있습니다. 의사 코드:
sql1 = select f_crm_id from d_dbname1.t_tbname1 where f_xxx_id = 926067 and f_mobile ='1234567891' limit 1; sq1.execute(); if no result sql1: sql1 = select f_crm_id from d_dbname1.t_tbname1 where f_xxx_id = 926067 and f_phone ='1234567891' limit 1; sql1.execute();
select a.f_crm_id from d_dbname1.t_tbname1 as a where (a.f_create_time > from_unixtime('1464397527') or a.f_modify_time > from_unixtime('1464397527') ) limit 0,200
(select a.f_crm_id from d_dbname1.t_tbname1 as a where a.f_create_time > from_unixtime('1464397527') limit 0,200 ) UNION ALL (select a.f_crm_id from d_dbname1.t_tbname1 as a where a.f_modify_time > from_unixtime('1464397527')and a.f_create_time <= from_unixtime('1464397527') limit 0,200)
sql1 = (select a.f_crm_id from d_dbname1.t_tbname1 as a where a.f_create_time > from_unixtime('1464397527') limit 0,200 ); sql1.execute(); sql1_count = sql1.result.count if sql1_count < 200 : sql2 = (select a.f_crm_id from d_dbname1.t_tbname1 as a where a.f_modify_time > from_unixtime('1464397527') and a.f_create_time <= from_unixtime('1464397527') limit 0, (200 - sql1_count) ); sql2.execute(); final_result = paste(sql1,sql2);
동일한 필드 또는 f_id=1 또는 f_id=100 -> f_id in (1,100) 과 같이 in으로 변경될 수 있습니다. 효율성 문제에 대해서는 mysql에서 또는 및 in의 효율성 문제 문서를 참조하세요.
위의 최적화 시나리오는 모두 InnoDB의 경우 스토리지 엔진입니다. MyISAM에서는 전체 테이블을 피하기 위해 인덱스를 사용할 수 있는 조건이 다릅니다.
위 내용은 MySQL에서 인덱스 컬럼에 OR 조건을 사용하지 않도록 하는 내용입니다. 더 많은 관련 내용은 PHP 중국어 홈페이지(m.sbmmt.com)를 참고해주세요!