MYSQL OR 대 IN 성능
다음과 같은 성능과 관련하여 차이가 있는지 궁금합니다.
SELECT ... FROM ... WHERE someFIELD IN(1,2,3,4)
SELECT ... FROM ... WHERE someFIELD between 0 AND 5
SELECT ... FROM ... WHERE someFIELD = 1 OR someFIELD = 2 OR someFIELD = 3 ...
또는 MySQL이 컴파일러가 코드를 최적화하는 것과 같은 방식으로 SQL을 최적화합니까?
편집 : 의견에 명시된 이유로 AND
의를 (으)로 변경했습니다 OR
.
나는 이것을 확실히 알아야했기 때문에 두 가지 방법을 모두 벤치마킹했다. 나는을 IN
사용하는 것보다 훨씬 빠르다는 것을 알게 되었습니다 OR
.
"의견"을주는 사람들을 믿지 마십시오. 과학은 테스트와 증거에 관한 것입니다.
나는 동등한 쿼리의 1000x 루프를 실행했다 (일관성을 위해 사용했다 sql_no_cache
).
IN
: 2.34969592094s
OR
: 5.83781504631s
업데이트 :
(6 년 전과 같이 원래 테스트의 소스 코드가 없지만이 테스트와 동일한 범위의 결과를 반환합니다)
이를 테스트하기위한 샘플 코드를 요청하는 가장 간단한 사용 사례는 다음과 같습니다. 구문 단순화를 위해 Eloquent를 사용하면 원시 SQL에 해당하는 것이 동일하게 실행됩니다.
$t = microtime(true);
for($i=0; $i<10000; $i++):
$q = DB::table('users')->where('id',1)
->orWhere('id',2)
->orWhere('id',3)
->orWhere('id',4)
->orWhere('id',5)
->orWhere('id',6)
->orWhere('id',7)
->orWhere('id',8)
->orWhere('id',9)
->orWhere('id',10)
->orWhere('id',11)
->orWhere('id',12)
->orWhere('id',13)
->orWhere('id',14)
->orWhere('id',15)
->orWhere('id',16)
->orWhere('id',17)
->orWhere('id',18)
->orWhere('id',19)
->orWhere('id',20)->get();
endfor;
$t2 = microtime(true);
echo $t."\n".$t2."\n".($t2-$t)."\n";
1482080514.3635
1482080517.3713
3.0078368186951
$t = microtime(true);
for($i=0; $i<10000; $i++):
$q = DB::table('users')->whereIn('id',[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])->get();
endfor;
$t2 = microtime(true);
echo $t."\n".$t2."\n".($t2-$t)."\n";
1482080534.0185
1482080536.178
2.1595389842987
또한 미래의 Google 직원을 대상으로 테스트를 수행했습니다. 반환 된 결과의 총 개수는 10000 중에서 7264입니다.
SELECT * FROM item WHERE id = 1 OR id = 2 ... id = 10000
이 쿼리는 0.1239
몇 초가 걸렸 습니다
SELECT * FROM item WHERE id IN (1,2,3,...10000)
이 쿼리는 0.0433
몇 초가 걸렸 습니다
IN
보다 3 배 빠르다 OR
BETWEEN이 다음과 같이 변환되어야하기 때문에 더 빠를 것이라고 생각합니다.
Field >= 0 AND Field <= 5
IN이 어쨌든 많은 OR 문으로 변환 될 것입니다. IN의 가치는 사용의 용이성입니다. (각 열 이름을 여러 번 입력해야하고 기존 논리와 함께 사용하기가 더 쉬워집니다. IN이 하나의 명령문이므로 AND / OR 우선 순위에 대해 걱정할 필요가 없습니다. 괄호로 묶어 하나의 조건으로 평가되도록합니다.)
귀하의 질문에 대한 유일한 실제 답변은 귀하의 질문을 제출하는 것 입니다. 그런 다음 특정 상황에서 가장 잘 작동하는 것을 알 수 있습니다.
그것은 당신이하고있는 것에 달려 있습니다. 범위의 넓이, 데이터 유형은 무엇입니까 (예에서는 숫자 데이터 유형을 사용하지만 귀하의 질문은 많은 다른 데이터 유형에도 적용될 수 있음).
이것은 두 가지 방식으로 쿼리를 작성하려는 인스턴스입니다. 작동시키고 EXPLAIN을 사용하여 실행 차이를 파악하십시오.
나는 이것에 대한 구체적인 대답이 있다고 확신하지만 이것이 실제로 주어진 질문에 대한 대답을 알아내는 방법입니다.
이것은 도움이 될 것입니다 : http://forge.mysql.com/wiki/Top10SQLPerformanceTips
감사합니다,
프랭크
sunseeker의 관찰에 대한 한 가지 설명은 MySQL이 실제로 정적 값이고 이진 검색을 사용하는 경우 IN 문의 값을 정렬하는 것입니다. 일반 OR 대안보다 효율적입니다. 어디에서 읽었는지 기억이 나지 않지만 sunseeker의 결과는 증거인 것 같습니다.
수락 된 답변은 이유를 설명하지 않습니다.
아래는 고성능 MySQL, 3 판에서 인용 한 것입니다.
많은 데이터베이스 서버에서 IN ()은 여러 OR 절에 대한 동의어 일뿐입니다. 두 개는 논리적으로 동일하기 때문입니다. MySQL에서는 IN () 목록의 값을 정렬하고 빠른 이진 검색을 사용하여 값이 목록에 있는지 여부를 확인합니다. 이것은 목록 크기에서 O (Log n)이지만, 동등한 OR 절 시리즈는 목록 크기에서 O (n)입니다 (즉, 큰 목록의 경우 훨씬 느림).
또는 가장 느립니다. IN 또는 BETWEEN이 더 빠른지 여부는 데이터에 따라 다르지만 BETWEEN이 인덱스에서 범위를 취할 수 있기 때문에 일반적으로 더 빠를 것으로 기대합니다 (someField가 색인화되었다고 가정).
안전하다고 생각했을 때만 ...
당신의 가치는 eq_range_index_dive_limit
무엇입니까? 특히, IN
조항 에 더 많거나 적은 항목이 있습니까?
여기에는 벤치 마크가 포함되지 않지만 내부 작업에 약간의 관심이 있습니다. 도구를 사용하여 무슨 일이 일어나고 있는지 확인하십시오-Optimizer Trace.
쿼리 : SELECT * FROM canada WHERE id ...
으로 OR
3 개 값의 추적의 일부는 다음과 같습니다
"condition_processing": {
"condition": "WHERE",
"original_condition": "((`canada`.`id` = 296172) or (`canada`.`id` = 295093) or (`canada`.`id` = 293626))",
"steps": [
{
"transformation": "equality_propagation",
"resulting_condition": "(multiple equal(296172, `canada`.`id`) or multiple equal(295093, `canada`.`id`) or multiple equal(293626, `canada`.`id`))"
},
...
"analyzing_range_alternatives": {
"range_scan_alternatives": [
{
"index": "id",
"ranges": [
"293626 <= id <= 293626",
"295093 <= id <= 295093",
"296172 <= id <= 296172"
],
"index_dives_for_eq_ranges": true,
"chosen": true
...
"refine_plan": [
{
"table": "`canada`",
"pushed_index_condition": "((`canada`.`id` = 296172) or (`canada`.`id` = 295093) or (`canada`.`id` = 293626))",
"table_condition_attached": null,
"access_type": "range"
}
]
ICP가 어떻게 제공되고 있는지 주목하십시오 ORs
. 이 의미 즉 OR
으로 설정되지 않은 IN
, 그리고 InnoDB는 한 무리의 수행됩니다 =
ICP를 통해 테스트를. (MyISAM을 고려할 가치가 있다고 생각하지 않습니다.)
(이것은 Percona의 5.6.22-71.0-log이며 id
보조 인덱스입니다.)
이제 몇 가지 값을 가진 IN ()
eq_range_index_dive_limit
= 10; 8 개의 값이 있습니다.
"condition_processing": {
"condition": "WHERE",
"original_condition": "(`canada`.`id` in (296172,295093,293626,295573,297148,296127,295588,295810))",
"steps": [
{
"transformation": "equality_propagation",
"resulting_condition": "(`canada`.`id` in (296172,295093,293626,295573,297148,296127,295588,295810))"
},
...
"analyzing_range_alternatives": {
"range_scan_alternatives": [
{
"index": "id",
"ranges": [
"293626 <= id <= 293626",
"295093 <= id <= 295093",
"295573 <= id <= 295573",
"295588 <= id <= 295588",
"295810 <= id <= 295810",
"296127 <= id <= 296127",
"296172 <= id <= 296172",
"297148 <= id <= 297148"
],
"index_dives_for_eq_ranges": true,
"chosen": true
...
"refine_plan": [
{
"table": "`canada`",
"pushed_index_condition": "(`canada`.`id` in (296172,295093,293626,295573,297148,296127,295588,295810))",
"table_condition_attached": null,
"access_type": "range"
}
]
로 IN
바뀌지 않은 것 같습니다 OR
.
참고 : 상수 값이 정렬되었습니다 . 이것은 두 가지 방법으로 유익 할 수 있습니다.
- 더 적게 뛰어 다니면 모든 값에 도달하기 위해 더 나은 캐싱, 더 적은 I / O가있을 수 있습니다.
- 두 개의 유사한 쿼리가 별도의 연결에서 발생하고 트랜잭션에있는 경우 목록이 겹치므로 교착 상태 대신 지연이 발생할 가능성이 높습니다.
마지막으로 값이 많은 IN ()
{
"condition_processing": {
"condition": "WHERE",
"original_condition": "(`canada`.`id` in (293831,292259,292881,293440,292558,295792,292293,292593,294337,295430,295034,297060,293811,295587,294651,295559,293213,295742,292605,296018,294529,296711,293919,294732,294689,295540,293000,296916,294433,297112,293815,292522,296816,293320,293232,295369,291894,293700,291839,293049,292738,294895,294473,294023,294173,293019,291976,294923,294797,296958,294075,293450,296952,297185,295351,295736,296312,294330,292717,294638,294713,297176,295896,295137,296573,292236,294966,296642,296073,295903,293057,294628,292639,293803,294470,295353,297196,291752,296118,296964,296185,295338,295956,296064,295039,297201,297136,295206,295986,292172,294803,294480,294706,296975,296604,294493,293181,292526,293354,292374,292344,293744,294165,295082,296203,291918,295211,294289,294877,293120,295387))",
"steps": [
{
"transformation": "equality_propagation",
"resulting_condition": "(`canada`.`id` in (293831,292259,292881,293440,292558,295792,292293,292593,294337,295430,295034,297060,293811,295587,294651,295559,293213,295742,292605,296018,294529,296711,293919,294732,294689,295540,293000,296916,294433,297112,293815,292522,296816,293320,293232,295369,291894,293700,291839,293049,292738,294895,294473,294023,294173,293019,291976,294923,294797,296958,294075,293450,296952,297185,295351,295736,296312,294330,292717,294638,294713,297176,295896,295137,296573,292236,294966,296642,296073,295903,293057,294628,292639,293803,294470,295353,297196,291752,296118,296964,296185,295338,295956,296064,295039,297201,297136,295206,295986,292172,294803,294480,294706,296975,296604,294493,293181,292526,293354,292374,292344,293744,294165,295082,296203,291918,295211,294289,294877,293120,295387))"
},
...
"analyzing_range_alternatives": {
"range_scan_alternatives": [
{
"index": "id",
"ranges": [
"291752 <= id <= 291752",
"291839 <= id <= 291839",
...
"297196 <= id <= 297196",
"297201 <= id <= 297201"
],
"index_dives_for_eq_ranges": false,
"rows": 111,
"chosen": true
...
"refine_plan": [
{
"table": "`canada`",
"pushed_index_condition": "(`canada`.`id` in (293831,292259,292881,293440,292558,295792,292293,292593,294337,295430,295034,297060,293811,295587,294651,295559,293213,295742,292605,296018,294529,296711,293919,294732,294689,295540,293000,296916,294433,297112,293815,292522,296816,293320,293232,295369,291894,293700,291839,293049,292738,294895,294473,294023,294173,293019,291976,294923,294797,296958,294075,293450,296952,297185,295351,295736,296312,294330,292717,294638,294713,297176,295896,295137,296573,292236,294966,296642,296073,295903,293057,294628,292639,293803,294470,295353,297196,291752,296118,296964,296185,295338,295956,296064,295039,297201,297136,295206,295986,292172,294803,294480,294706,296975,296604,294493,293181,292526,293354,292374,292344,293744,294165,295082,296203,291918,295211,294289,294877,293120,295387))",
"table_condition_attached": null,
"access_type": "range"
}
]
참고 사항 : 부피가 커서 이것이 필요했습니다.
@@global.optimizer_trace_max_mem_size = 32222;
나는 그들이 똑같을 것이라고, 다음을 수행하여 테스트를 실행할 수 있습니다.
"in (1,2,3,4)"를 500 번 반복하고 시간이 얼마나 걸리는지보십시오. "= 1 또는 = 2 or = 3 ..."버전을 500 번 반복하여 얼마나 오래 실행되는지 확인하십시오.
someField가 인덱스이고 테이블이 크면 조인 방법을 사용해 볼 수도 있습니다.
SELECT ...
FROM ...
INNER JOIN (SELECT 1 as newField UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) dt ON someFIELD =newField
위의 SQL Server에서 조인 방법을 시도했지만 in (1,2,3,4)와 거의 동일하며 둘 다 클러스터 인덱스 검색을 수행합니다. MySQL이 어떻게 처리 할 지 잘 모르겠습니다.
다음은 MySQL 5.6 @SQLFiddle을 사용한 6 가지 쿼리에 대한 세부 정보입니다.
요약하면 6 개의 쿼리가 독립적으로 인덱싱 된 열을 다루고 데이터 유형 당 2 개의 쿼리가 사용되었습니다. IN () 또는 OR 사용 여부에 관계없이 모든 쿼리에서 인덱스를 사용했습니다.
| ORs | IN()
integer | uses index | uses index
date | uses index | uses index
varchar | uses index | uses index
나는 단지 OR을 사용하여 인덱스를 사용할 수 없다는 진술을 발표하고 싶었습니다. 사실이 아닙니다. 다음 예에서 6 개의 조회로 OR을 사용하는 조회에서 색인을 사용할 수 있습니다.
또한 IN ()이 OR 세트의 구문 단축키라는 사실을 많은 사람들이 무시한 것 같습니다. IN () -v- OR을 사용하는 것 사이의 소규모 성능 차이는 극도로 (마침내) 한계입니다.
더 큰 규모의 IN ()은 확실히 더 편리하지만, 논리적으로 한 세트의 OR 조건과 동일합니다. 각 쿼리마다 상황이 변경되므로 테이블에서 쿼리를 테스트하는 것이 항상 가장 좋습니다.
6 개의 Explain 계획 요약, 모두 "인덱스 조건 사용"(오른쪽 스크롤)
Query select_type table type possible_keys key key_len ref rows filtered Extra
------------- --------- ------- --------------- ----------- --------- ----- ------ ---------- -----------------------
Integers using OR SIMPLE mytable range aNum_idx aNum_idx 4 10 100.00 Using index condition
Integers using IN SIMPLE mytable range aNum_idx aNum_idx 4 10 100.00 Using index condition
Dates using OR SIMPLE mytable range aDate_idx aDate_idx 6 7 100.00 Using index condition
Dates using IN SIMPLE mytable range aDate_idx aDate_idx 6 7 100.00 Using index condition
Varchar using OR SIMPLE mytable range aName_idx aName_idx 768 10 100.00 Using index condition
Varchar using IN SIMPLE mytable range aName_idx aName_idx 768 10 100.00 Using index condition
MySQL 5.6 스키마 설정 :
CREATE TABLE `myTable` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
`aName` varchar(255) default NULL,
`aDate` datetime,
`aNum` mediumint(8),
PRIMARY KEY (`id`)
) AUTO_INCREMENT=1;
ALTER TABLE `myTable` ADD INDEX `aName_idx` (`aName`);
ALTER TABLE `myTable` ADD INDEX `aDate_idx` (`aDate`);
ALTER TABLE `myTable` ADD INDEX `aNum_idx` (`aNum`);
INSERT INTO `myTable` (`aName`,`aDate`)
VALUES
("Daniel","2017-09-19 01:22:31")
,("Quentin","2017-06-03 01:06:45")
,("Chester","2017-06-14 17:49:36")
,("Lev","2017-08-30 06:27:59")
,("Garrett","2018-10-04 02:40:37")
,("Lane","2017-01-22 17:11:21")
,("Chaim","2017-09-20 11:13:46")
,("Kieran","2018-03-10 18:37:26")
,("Cedric","2017-05-20 16:25:10")
,("Conan","2018-07-10 06:29:39")
,("Rudyard","2017-07-14 00:04:00")
,("Chadwick","2018-08-18 08:54:08")
,("Darius","2018-10-02 06:55:56")
,("Joseph","2017-06-19 13:20:33")
,("Wayne","2017-04-02 23:20:25")
,("Hall","2017-10-13 00:17:24")
,("Craig","2016-12-04 08:15:22")
,("Keane","2018-03-12 04:21:46")
,("Russell","2017-07-14 17:21:58")
,("Seth","2018-07-25 05:51:30")
,("Cole","2018-06-09 15:32:53")
,("Donovan","2017-08-12 05:21:35")
,("Damon","2017-06-27 03:44:19")
,("Brian","2017-02-01 23:35:20")
,("Harper","2017-08-25 04:29:27")
,("Chandler","2017-09-30 23:54:06")
,("Edward","2018-07-30 12:18:07")
,("Curran","2018-05-23 09:31:53")
,("Uriel","2017-05-08 03:31:43")
,("Honorato","2018-04-07 14:57:53")
,("Griffin","2017-01-07 23:35:31")
,("Hasad","2017-05-15 05:32:41")
,("Burke","2017-07-04 01:11:19")
,("Hyatt","2017-03-14 17:12:28")
,("Brenden","2017-10-17 05:16:14")
,("Ryan","2018-10-10 08:07:55")
,("Giacomo","2018-10-06 14:21:21")
,("James","2018-02-06 02:45:59")
,("Colt","2017-10-10 08:11:26")
,("Kermit","2017-09-18 16:57:16")
,("Drake","2018-05-20 22:08:36")
,("Berk","2017-04-16 17:39:32")
,("Alan","2018-09-01 05:33:05")
,("Deacon","2017-04-20 07:03:05")
,("Omar","2018-03-02 15:04:32")
,("Thaddeus","2017-09-19 04:07:54")
,("Troy","2016-12-13 04:24:08")
,("Rogan","2017-11-02 00:03:25")
,("Grant","2017-08-21 01:45:16")
,("Walker","2016-11-26 15:54:52")
,("Clarke","2017-07-20 02:26:56")
,("Clayton","2018-08-16 05:09:29")
,("Denton","2018-08-11 05:26:05")
,("Nicholas","2018-07-19 09:29:55")
,("Hashim","2018-08-10 20:38:06")
,("Todd","2016-10-25 01:01:36")
,("Xenos","2017-05-11 22:50:35")
,("Bert","2017-06-17 18:08:21")
,("Oleg","2018-01-03 13:10:32")
,("Hall","2018-06-04 01:53:45")
,("Evan","2017-01-16 01:04:25")
,("Mohammad","2016-11-18 05:42:52")
,("Armand","2016-12-18 06:57:57")
,("Kaseem","2018-06-12 23:09:57")
,("Colin","2017-06-29 05:25:52")
,("Arthur","2016-12-29 04:38:13")
,("Xander","2016-11-14 19:35:32")
,("Dante","2016-12-01 09:01:04")
,("Zahir","2018-02-17 14:44:53")
,("Raymond","2017-03-09 05:33:06")
,("Giacomo","2017-04-17 06:12:52")
,("Fulton","2017-06-04 00:41:57")
,("Chase","2018-01-14 03:03:57")
,("William","2017-05-08 09:44:59")
,("Fuller","2017-03-31 20:35:20")
,("Jarrod","2017-02-15 02:45:29")
,("Nissim","2018-03-11 14:19:25")
,("Chester","2017-11-05 00:14:27")
,("Perry","2017-12-24 11:58:04")
,("Theodore","2017-06-26 12:34:12")
,("Mason","2017-10-02 03:53:49")
,("Brenden","2018-10-08 10:09:47")
,("Jerome","2017-11-05 20:34:25")
,("Keaton","2018-08-18 00:55:56")
,("Tiger","2017-05-21 16:59:07")
,("Benjamin","2018-04-10 14:46:36")
,("John","2018-09-05 18:53:03")
,("Jakeem","2018-10-11 00:17:38")
,("Kenyon","2017-12-18 22:19:29")
,("Ferris","2017-03-29 06:59:13")
,("Hoyt","2017-01-03 03:48:56")
,("Fitzgerald","2017-07-27 11:27:52")
,("Forrest","2017-10-05 23:14:21")
,("Jordan","2017-01-11 03:48:09")
,("Lev","2017-05-25 08:03:39")
,("Chase","2017-06-18 19:09:23")
,("Ryder","2016-12-13 12:50:50")
,("Malik","2017-11-19 15:15:55")
,("Zeph","2018-04-04 11:22:12")
,("Amala","2017-01-29 07:52:17")
;
.
update MyTable
set aNum = id
;
쿼리 1 :
select 'aNum by OR' q, mytable.*
from mytable
where aNum = 12
OR aNum = 22
OR aNum = 27
OR aNum = 32
OR aNum = 42
OR aNum = 52
OR aNum = 62
OR aNum = 65
OR aNum = 72
OR aNum = 82
결과 :
| q | id | aName | aDate | aNum |
|------------|----|----------|----------------------|------|
| aNum by OR | 12 | Chadwick | 2018-08-18T08:54:08Z | 12 |
| aNum by OR | 22 | Donovan | 2017-08-12T05:21:35Z | 22 |
| aNum by OR | 27 | Edward | 2018-07-30T12:18:07Z | 27 |
| aNum by OR | 32 | Hasad | 2017-05-15T05:32:41Z | 32 |
| aNum by OR | 42 | Berk | 2017-04-16T17:39:32Z | 42 |
| aNum by OR | 52 | Clayton | 2018-08-16T05:09:29Z | 52 |
| aNum by OR | 62 | Mohammad | 2016-11-18T05:42:52Z | 62 |
| aNum by OR | 65 | Colin | 2017-06-29T05:25:52Z | 65 |
| aNum by OR | 72 | Fulton | 2017-06-04T00:41:57Z | 72 |
| aNum by OR | 82 | Brenden | 2018-10-08T10:09:47Z | 82 |
쿼리 2 :
select 'aNum by IN' q, mytable.*
from mytable
where aNum IN (
12
, 22
, 27
, 32
, 42
, 52
, 62
, 65
, 72
, 82
)
결과 :
| q | id | aName | aDate | aNum |
|------------|----|----------|----------------------|------|
| aNum by IN | 12 | Chadwick | 2018-08-18T08:54:08Z | 12 |
| aNum by IN | 22 | Donovan | 2017-08-12T05:21:35Z | 22 |
| aNum by IN | 27 | Edward | 2018-07-30T12:18:07Z | 27 |
| aNum by IN | 32 | Hasad | 2017-05-15T05:32:41Z | 32 |
| aNum by IN | 42 | Berk | 2017-04-16T17:39:32Z | 42 |
| aNum by IN | 52 | Clayton | 2018-08-16T05:09:29Z | 52 |
| aNum by IN | 62 | Mohammad | 2016-11-18T05:42:52Z | 62 |
| aNum by IN | 65 | Colin | 2017-06-29T05:25:52Z | 65 |
| aNum by IN | 72 | Fulton | 2017-06-04T00:41:57Z | 72 |
| aNum by IN | 82 | Brenden | 2018-10-08T10:09:47Z | 82 |
쿼리 3 :
select 'adate by OR' q, mytable.*
from mytable
where aDate= str_to_date("2017-02-15 02:45:29",'%Y-%m-%d %h:%i:%s')
OR aDate = str_to_date("2018-03-10 18:37:26",'%Y-%m-%d %h:%i:%s')
OR aDate = str_to_date("2017-05-20 16:25:10",'%Y-%m-%d %h:%i:%s')
OR aDate = str_to_date("2018-07-10 06:29:39",'%Y-%m-%d %h:%i:%s')
OR aDate = str_to_date("2017-07-14 00:04:00",'%Y-%m-%d %h:%i:%s')
OR aDate = str_to_date("2018-08-18 08:54:08",'%Y-%m-%d %h:%i:%s')
OR aDate = str_to_date("2018-10-02 06:55:56",'%Y-%m-%d %h:%i:%s')
OR aDate = str_to_date("2017-04-20 07:03:05",'%Y-%m-%d %h:%i:%s')
OR aDate = str_to_date("2018-03-02 15:04:32",'%Y-%m-%d %h:%i:%s')
OR aDate = str_to_date("2017-09-19 04:07:54",'%Y-%m-%d %h:%i:%s')
OR aDate = str_to_date("2016-12-13 04:24:08",'%Y-%m-%d %h:%i:%s')
결과 :
| q | id | aName | aDate | aNum |
|-------------|----|----------|----------------------|------|
| adate by OR | 47 | Troy | 2016-12-13T04:24:08Z | 47 |
| adate by OR | 76 | Jarrod | 2017-02-15T02:45:29Z | 76 |
| adate by OR | 44 | Deacon | 2017-04-20T07:03:05Z | 44 |
| adate by OR | 46 | Thaddeus | 2017-09-19T04:07:54Z | 46 |
| adate by OR | 10 | Conan | 2018-07-10T06:29:39Z | 10 |
| adate by OR | 12 | Chadwick | 2018-08-18T08:54:08Z | 12 |
| adate by OR | 13 | Darius | 2018-10-02T06:55:56Z | 13 |
쿼리 4 :
select 'adate by IN' q, mytable.*
from mytable
where aDate IN (
str_to_date("2017-02-15 02:45:29",'%Y-%m-%d %h:%i:%s')
, str_to_date("2018-03-10 18:37:26",'%Y-%m-%d %h:%i:%s')
, str_to_date("2017-05-20 16:25:10",'%Y-%m-%d %h:%i:%s')
, str_to_date("2018-07-10 06:29:39",'%Y-%m-%d %h:%i:%s')
, str_to_date("2017-07-14 00:04:00",'%Y-%m-%d %h:%i:%s')
, str_to_date("2018-08-18 08:54:08",'%Y-%m-%d %h:%i:%s')
, str_to_date("2018-10-02 06:55:56",'%Y-%m-%d %h:%i:%s')
, str_to_date("2017-04-20 07:03:05",'%Y-%m-%d %h:%i:%s')
, str_to_date("2018-03-02 15:04:32",'%Y-%m-%d %h:%i:%s')
, str_to_date("2017-09-19 04:07:54",'%Y-%m-%d %h:%i:%s')
, str_to_date("2016-12-13 04:24:08",'%Y-%m-%d %h:%i:%s')
)
결과 :
| q | id | aName | aDate | aNum |
|-------------|----|----------|----------------------|------|
| adate by IN | 47 | Troy | 2016-12-13T04:24:08Z | 47 |
| adate by IN | 76 | Jarrod | 2017-02-15T02:45:29Z | 76 |
| adate by IN | 44 | Deacon | 2017-04-20T07:03:05Z | 44 |
| adate by IN | 46 | Thaddeus | 2017-09-19T04:07:54Z | 46 |
| adate by IN | 10 | Conan | 2018-07-10T06:29:39Z | 10 |
| adate by IN | 12 | Chadwick | 2018-08-18T08:54:08Z | 12 |
| adate by IN | 13 | Darius | 2018-10-02T06:55:56Z | 13 |
쿼리 5 :
select 'name by OR' q, mytable.*
from mytable
where aname = 'Alan'
OR aname = 'Brian'
OR aname = 'Chandler'
OR aname = 'Darius'
OR aname = 'Evan'
OR aname = 'Ferris'
OR aname = 'Giacomo'
OR aname = 'Hall'
OR aname = 'James'
OR aname = 'Jarrod'
결과 :
| q | id | aName | aDate | aNum |
|-------------|----|----------|----------------------|------|
| name by OR | 43 | Alan | 2018-09-01T05:33:05Z | 43 |
| name by OR | 24 | Brian | 2017-02-01T23:35:20Z | 24 |
| name by OR | 26 | Chandler | 2017-09-30T23:54:06Z | 26 |
| name by OR | 13 | Darius | 2018-10-02T06:55:56Z | 13 |
| name by OR | 61 | Evan | 2017-01-16T01:04:25Z | 61 |
| name by OR | 90 | Ferris | 2017-03-29T06:59:13Z | 90 |
| name by OR | 37 | Giacomo | 2018-10-06T14:21:21Z | 37 |
| name by OR | 71 | Giacomo | 2017-04-17T06:12:52Z | 71 |
| name by OR | 16 | Hall | 2017-10-13T00:17:24Z | 16 |
| name by OR | 60 | Hall | 2018-06-04T01:53:45Z | 60 |
| name by OR | 38 | James | 2018-02-06T02:45:59Z | 38 |
| name by OR | 76 | Jarrod | 2017-02-15T02:45:29Z | 76 |
쿼리 6 :
select 'name by IN' q, mytable.*
from mytable
where aname IN (
'Alan'
,'Brian'
,'Chandler'
, 'Darius'
, 'Evan'
, 'Ferris'
, 'Giacomo'
, 'Hall'
, 'James'
, 'Jarrod'
)
결과 :
| q | id | aName | aDate | aNum |
|------------|----|----------|----------------------|------|
| name by IN | 43 | Alan | 2018-09-01T05:33:05Z | 43 |
| name by IN | 24 | Brian | 2017-02-01T23:35:20Z | 24 |
| name by IN | 26 | Chandler | 2017-09-30T23:54:06Z | 26 |
| name by IN | 13 | Darius | 2018-10-02T06:55:56Z | 13 |
| name by IN | 61 | Evan | 2017-01-16T01:04:25Z | 61 |
| name by IN | 90 | Ferris | 2017-03-29T06:59:13Z | 90 |
| name by IN | 37 | Giacomo | 2018-10-06T14:21:21Z | 37 |
| name by IN | 71 | Giacomo | 2017-04-17T06:12:52Z | 71 |
| name by IN | 16 | Hall | 2017-10-13T00:17:24Z | 16 |
| name by IN | 60 | Hall | 2018-06-04T01:53:45Z | 60 |
| name by IN | 38 | James | 2018-02-06T02:45:59Z | 38 |
| name by IN | 76 | Jarrod | 2017-02-15T02:45:29Z | 76 |
컴파일러가 이러한 유형의 쿼리를 최적화하는 방식에 대해 이해 한 것에서 IN 절을 사용하는 것이 여러 OR 절보다 효율적입니다. BETWEEN 절을 사용할 수있는 값이 있으면 더 효율적입니다.
Field에 대한 색인이있는 한 BETWEEN 은이를 사용하여 한쪽 끝을 빨리 찾은 다음 다른 쪽 끝을 가로 지 릅니다. 이것이 가장 효율적입니다.
내가 본 모든 EXPLAIN은 "IN (...)"과 "... OR ..."이 상호 교환 가능하고 똑같이 (비효율적 임) 보여줍니다. 옵티마이 저가 간격을 구성하는지 여부를 알 수있는 방법이 없기 때문에 예상 한 것입니다. 개별 값의 UNION ALL SELECT와 동일합니다.
2018 : IN 이 더 빠릅니다. 그러나 > = && <= 는 IN 보다 훨씬 빠릅니다 .
여기 내 기준이 있습니다.
참고 URL : https://stackoverflow.com/questions/782915/mysql-or-vs-in-performance
'IT story' 카테고리의 다른 글
git-upload-pack : 원격 Git 저장소를 복제 할 때 명령을 찾을 수 없습니다 (0) | 2020.05.26 |
---|---|
PowerShell에서 로컬 호스트 이름을 얻으려면 어떻게합니까? (0) | 2020.05.26 |
리눅스에서 터미널 히스토리 삭제하기 (0) | 2020.05.26 |
div에서 긴 단어를 단어 줄 바꿈하는 방법이 있습니까? (0) | 2020.05.26 |
Swift에서 오류 유형으로 현지화 된 설명을 제공하는 방법은 무엇입니까? (0) | 2020.05.26 |