MYSQL OR 与 IN 性能
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/782915/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
MYSQL OR vs IN performance
提问by Scott
I am wondering if there is any difference in regards to performance between the following
我想知道以下在性能方面是否有任何差异
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 ...
or will MySQL optimize the SQL in the same way compilers will optimize code ?
还是 MySQL 会像编译器优化代码一样优化 SQL?
EDIT: Changed the AND
's to OR
's for the reason stated in the comments.
编辑:由于评论中所述的原因,将 's更改为AND
's OR
。
回答by Cyril
I needed to know this for sure, so I benchmarked both methods. I consistenly found IN
to be much faster than using OR
.
我需要确定知道这一点,所以我对这两种方法进行了基准测试。我一直发现IN
比使用OR
.
Do not believe people who give their "opinion", science is all about testing and evidence.
不要相信给出“意见”的人,科学就是测试和证据。
I ran a loop of 1000x the equivalent queries (for consistency, I used sql_no_cache
):
我运行了 1000 倍等效查询的循环(为了一致性,我使用了sql_no_cache
):
IN
: 2.34969592094s
IN
: 2.34969592094s
OR
: 5.83781504631s
OR
: 5.83781504631s
Update:
(I don't have the source code for the original test, as it was 6 years ago, though it returns a result in the same range as this test)
更新:(
我没有原始测试的源代码,因为它是 6 年前的,尽管它返回的结果与此测试的范围相同)
In request for some sample code to test this, here is the simplest possible use case. Using Eloquent for syntax simplicity, raw SQL equivalent executes the same.
为了提供一些示例代码来测试这一点,这里是最简单的用例。使用 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
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
1482080534.0185
1482080536.178
2.1595389842987
回答by Ergec
I also did a test for future Googlers. Total count of returned results is 7264 out of 10000
我还为未来的 Google 员工做了一个测试。返回结果的总数为 10000 个中的 7264 个
SELECT * FROM item WHERE id = 1 OR id = 2 ... id = 10000
This query took 0.1239
seconds
这个查询花了0.1239
几秒钟
SELECT * FROM item WHERE id IN (1,2,3,...10000)
This query took 0.0433
seconds
这个查询花了0.0433
几秒钟
IN
is 3 times faster than OR
IN
比它快 3 倍 OR
回答by Jacob
The accepted answer doesn't explain the reason.
接受的答案没有解释原因。
Below are quoted from High Performance MySQL, 3rd Edition.
以下引用自高性能 MySQL,第 3 版。
In many database servers, IN() is just a synonym for multiple OR clauses, because the two are logically equivalent. Not so in MySQL, which sorts the values in the IN() list and uses a fast binary search to see whether a value is in the list. This is O(Log n) in the size of the list, whereas an equivalent series of OR clauses is O(n) in the size of the list (i.e., much slower for large lists)
在许多数据库服务器中,IN() 只是多个 OR 子句的同义词,因为两者在逻辑上是等价的。在 MySQL 中不是这样,它对 IN() 列表中的值进行排序并使用快速二进制搜索来查看某个值是否在列表中。这是列表大小的 O(Log n),而等效的一系列 OR 子句在列表的大小上是 O(n)(即,对于大列表要慢得多)
回答by beach
I think the BETWEEN will be faster since it should be converted into:
我认为 BETWEEN 会更快,因为它应该转换为:
Field >= 0 AND Field <= 5
It is my understanding that an IN will be converted to a bunch of OR statements anyway. The value of IN is the ease of use. (Saving on having to type each column name multiple times and also makes it easier to use with existing logic - you don't have to worry about AND/OR precedence because the IN is one statement. With a bunch of OR statements, you have to ensure you surround them with parentheses to make sure they are evaluated as one condition.)
我的理解是 IN 无论如何都会转换为一堆 OR 语句。IN的价值在于易用性。(不必多次键入每个列名,并且还可以更轻松地使用现有逻辑 - 您不必担心 AND/OR 优先级,因为 IN 是一个语句。使用一堆 OR 语句,您有以确保用括号将它们括起来,以确保它们被评估为一种条件。)
The only real answer to your question is PROFILE YOUR QUERIES. Then you will know what works best in your particular situation.
您问题的唯一真正答案是PROFILE YOUR QUERIES。然后你就会知道什么在你的特定情况下最有效。
回答by Frank V
It depends on what you are doing; how wide is the range, what is the data type (I know your example uses a numeric data type but your question can also apply to a lot of different data types).
这取决于你在做什么;范围有多宽,数据类型是什么(我知道您的示例使用数字数据类型,但您的问题也适用于许多不同的数据类型)。
This is an instance where you want to write the query both ways; get it working and then use EXPLAIN to figure out the execution differences.
这是您想要双向编写查询的实例;让它工作,然后使用 EXPLAIN 找出执行差异。
I'm sure there is a concrete answer to this but this is how I would, practically speaking, figure out the answer for my given question.
我确信对此有一个具体的答案,但实际上,这就是我为给定问题找出答案的方式。
This might be of some help: http://forge.mysql.com/wiki/Top10SQLPerformanceTips
这可能会有所帮助:http: //forge.mysql.com/wiki/Top10SQLPerformanceTips
Regards,
Frank
问候,
弗兰克
回答by user658991
I think one explanation to sunseeker's observation is MySQL actually sort the values in the IN statement if they are all static values and using binary search, which is more efficient than the plain OR alternative. I can't remember where I've read that, but sunseeker's result seems to be a proof.
我认为对 sunseeker 观察的一种解释是 MySQL 实际上对 IN 语句中的值进行排序,如果它们都是静态值并使用二进制搜索,这比普通的 OR 替代方案更有效。我不记得我在哪里读到的,但 sunseeker 的结果似乎是一个证明。
回答by Rick James
Just when you thought it was safe...
就在你以为安全的时候……
What is your value of eq_range_index_dive_limit
? In particular, do you have more or fewer items in the IN
clause?
你的价值是eq_range_index_dive_limit
什么?特别是,您在IN
子句中的条目是更多还是更少?
This will not include a Benchmark, but will peer into the inner workings a little. Let's use a tool to see what is going on -- Optimizer Trace.
这将不包括基准测试,但会深入了解内部工作原理。让我们使用一个工具来看看发生了什么——Optimizer Trace。
The query: SELECT * FROM canada WHERE id ...
查询: SELECT * FROM canada WHERE id ...
With an OR
of 3 values, part of the trace looks like:
使用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"
}
]
Note how ICP is being given ORs
. This impliesthat OR
is not turned into IN
, and InnoDB will be performing a bunch of =
tests through ICP. (I do not feel it is worth considering MyISAM.)
注意 ICP 是如何给出的ORs
。这意味着这OR
是不是变成IN
,和InnoDB将表演一堆=
通过ICP测试。(我觉得不值得考虑 MyISAM。)
(This is Percona's 5.6.22-71.0-log; id
is a secondary index.)
(这是 Percona 的 5.6.22-71.0-log;id
是二级索引。)
Now for IN() with a few values
现在 IN() 有几个值
eq_range_index_dive_limit
= 10; there are 8 values.
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"
}
]
Note that the IN
does not seem to be turned into OR
.
请注意,IN
似乎没有变成OR
.
A side note: Notice that the constant values were sorted. This can be beneficial in two ways:
旁注:请注意,常量值已排序。这在两个方面是有益的:
- By jumping around less, there may be better caching, less I/O to get to all the values.
- If two similar queries are coming from separate connections, and they are in transactions, there is a better chance of getting a delay instead of a deadlock due to overlapping lists.
- 通过减少跳转,可能会有更好的缓存,更少的 I/O 来获取所有值。
- 如果两个相似的查询来自不同的连接,并且它们在事务中,则由于重叠列表,更有可能获得延迟而不是死锁。
Finally, IN() with a lots of values
最后,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"
}
]
Side note: I needed this due to the bulkiness of the trace:
旁注:由于跟踪量很大,我需要这个:
@@global.optimizer_trace_max_mem_size = 32222;
回答by Used_By_Already
Below are details of 6 queries using MySQL 5.6 @SQLFiddle
以下是使用 MySQL 5.6 @SQLFiddle 的 6 个查询的详细信息
In summary the 6 queries cover independently indexed columns and 2 queries were used per data type. All queries resulted in use of an index regardless of IN() or ORs being used.
总之,6 个查询涵盖了独立索引的列,每个数据类型使用了 2 个查询。无论使用的是 IN() 还是 OR,所有查询都会导致使用索引。
| ORs | IN()
integer | uses index | uses index
date | uses index | uses index
varchar | uses index | uses index
I really just wanted to debunk statements made that OR means no index can be used. This isn't true. Indexes can be used in queries using OR as the 6 queries in the following examples display.
我真的只是想揭穿 OR 表示无法使用索引的声明。这不是真的。可以在使用 OR 的查询中使用索引,如以下示例中显示的 6 个查询。
Also it seems to me that many have ignored the fact that IN() is a syntax shortcut for a set of ORs. At small scale perfomance differences between using IN() -v- OR are extremely (infintessinally) marginal.
在我看来,很多人都忽略了 IN() 是一组 OR 的语法快捷方式这一事实。在小规模下,使用 IN() -v- OR 之间的性能差异非常(无限)微不足道。
While at larger scale IN() is certainly more convenient, but it sill equates to a set of OR conditions logically. Circumstance change for each query so testing your query on your tables is always best.
虽然在更大规模的情况下 IN() 当然更方便,但它在逻辑上等同于一组 OR 条件。每个查询的情况都会发生变化,因此在您的表上测试您的查询总是最好的。
Summary of the 6 explain plans, all "Using index condition" (scroll right)
6个解释计划的总结,全部“使用索引条件”(向右滚动)
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 Schema Setup:
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
;
Query 1:
查询 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 |
Query 2:
查询 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 |
Query 3:
查询 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 |
Query 4:
查询 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 |
Query 5:
查询 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 |
Query 6:
查询 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 |
回答by Greg
OR will be slowest. Whether IN or BETWEEN is faster will depend on your data, but I'd expect BETWEEN to be faster normally as it can simple take a range from an index (assuming someField is indexed).
OR 将是最慢的。IN 或 BETWEEN 是否更快取决于您的数据,但我希望 BETWEEN 通常更快,因为它可以简单地从索引中获取一个范围(假设 someField 已被索引)。
回答by KM.
I'll bet they are the same, you can run a test by doing the following:
我敢打赌它们是相同的,您可以通过执行以下操作来运行测试:
loop over the "in (1,2,3,4)" 500 times and see how long it takes. loop over the "=1 or =2 or=3..." version 500 times and seeing how long it runs.
循环“in (1,2,3,4)” 500 次,看看需要多长时间。循环“=1 或=2 或=3...”版本500 次,看看它运行了多长时间。
you could also try a join way, if someField is an index and your table is big it could be faster...
你也可以尝试连接方式,如果 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
I tried the join method above on my SQL Server and it is nearly the same as the in (1,2,3,4), and they both result in a clustered index seek. I'm not sure how MySQL will handle them.
我在我的 SQL Server 上尝试了上面的 join 方法,它与 in (1,2,3,4) 几乎相同,它们都导致聚集索引查找。我不确定 MySQL 将如何处理它们。