当前位置: 首页 > 面试题库 >

MySQL Query IN()子句在索引列上变慢

车诚
2023-03-14
问题内容

我有一个由PHP脚本生成的MySQL查询,该查询将如下所示:

SELECT * FROM Recipe_Data WHERE 404_Without_200 = 0 AND Failures_Without_Success = 0 AND RHD_No IN (10, 24, 34, 41, 43, 51, 57, 59, 61, 67, 84, 90, 272, 324, 402, 405, 414, 498, 500, 501, 510, 559, 562, 595, 632, 634, 640, 643, 647, 651, 703, 714, 719, 762, 765, 776, 796, 812, 814, 815, 822, 848, 853, 855, 858, 866, 891, 920, 947, 956, 962, 968, 1049, 1054, 1064, 1065, 1070, 1100, 1113, 1119, 1130, 1262, 1287, 1292, 1313, 1320, 1327, 1332, 1333, 1335, 1340, 1343, 1344, 1346, 1349, 1352, 1358, 1362, 1365, 1482, 1495, 1532, 1533, 1537, 1549, 1550, 1569, 1571, 1573, 1574, 1596, 1628, 1691, 1714, 1720, 1735, 1755, 1759, 1829, 1837, 1844, 1881, 1919, 2005, 2022, 2034, 2035, 2039, 2054, 2076, 2079, 2087, 2088, 2089, 2090, 2091, 2092, 2154, 2155, 2156, 2157, 2160, 2162, 2164, 2166, 2169, 2171, 2174, 2176, 2178, 2179, 2183, 2185, 2186, 2187, 2201, 2234, 2236, 2244, 2245, 2250, 2255, 2260, 2272, 2280, 2281, 2282, 2291, 2329, 2357, 2375, 2444, 2451, 2452, 2453, 2454, 2456, 2457, 2460, 2462, 2464, 2465, 2467, 2468, 2469, 2470, 2473, 2474, 2481, 2485, 2487, 2510, 2516, 2519, 2525, 2540, 2545, 2547, 2553, 2571, 2579, 2580, 2587, 2589, 2597, 2602, 2611, 2629, 2660, 2662, 2700, 2756, 2825, 2833, 2835, 2858, 2958, 2963, 2964, 3009, 3090, 3117, 3118, 3120, 3121, 3122, 3123, 3126, 3127, 3129, 3130, 3133, 3135, 3137, 3138, 3139, 3141, 3142, 3145, 3146, 3147, 3151, 3152, 3155, 3193, 3201, 3204, 3219, 3221, 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3231, 3232, 3233, 3234, 3235, 3237, 3239, 3246, 3250, 3253, 3259, 3261, 3291, 3315, 3328, 3377, 3381, 3383, 3384, 3385, 3387, 3388, 3389, 3390, 3396, 3436, 3463, 3465, 3467, 3470, 3471, 3484, 3507, 3515, 3554, 3572, 3641, 3672, 3683, 3689, 3690, 3692, 3693, 3694, 3697, 3698, 3705, 3711, 3713, 3715, 3716, 3717, 3719, 3720, 3722, 3726, 3727, 3732, 3737, 3763, 3767, 3770, 3771, 3772, 3773, 3803, 3810, 3812, 3816, 3846, 3847, 3848, 3851, 3874, 3882, 3902, 3903, 3906, 3908, 3916, 3924, 3967, 3987, 4006, 4030, 4043, 4045, 4047, 4058, 4067, 4107, 4108, 4114, 4115, 4131, 4132, 4133, 4137, 4138, 4139, 4140, 4141, 4142, 4146, 4150, 4151, 4152, 4153, 4157, 4158, 4160, 4163, 4166, 4167, 4171, 4179, 4183, 4221, 4225, 4242, 4257, 4435, 4437, 4438, 4443, 4446, 4449, 4450, 4451, 4452, 4454, 4460, 4550, 4557, 4618, 4731, 4775, 4804, 4972, 5025, 5026, 5039, 5042, 5294, 5578, 5580, 5599, 5602, 5649, 5726, 5779, 5783, 5931, 5934, 5936, 5939, 5940, 5941, 5978, 6044, 6056, 6113, 6116, 6118, 6122, 6123, 6125, 6127, 6128, 6129, 6130, 6131, 6135, 6141, 6145, 6147, 6150, 6152, 6153, 6154, 6160, 6166, 6169);

RHD_No列是此数据库的主键,总共约有40万行。问题是,查询速度非常慢,通常需要2秒钟左右,但我发现查询的时间长达10秒钟。

当我尝试解释查询时,一切似乎都应该没问题:

+----+-------------+-------------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table       | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | Recipe_Data | range | PRIMARY       | PRIMARY | 4       | NULL |  420 | Using where |
+----+-------------+-------------+-------+---------------+---------+---------+------+------+-------------+

当我配置查询时,我得到:

mysql> show profile;
+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| starting                       | 0.000015 |
| checking query cache for query | 0.000266 |
| Opening tables                 | 0.000009 |
| System lock                    | 0.000004 |
| Table lock                     | 0.000006 |
| init                           | 0.000115 |
| optimizing                     | 0.000038 |
| statistics                     | 0.000797 |
| preparing                      | 0.000047 |
| executing                      | 0.000002 |
| Sending data                   | 2.675270 |
| end                            | 0.000007 |
| query end                      | 0.000003 |
| freeing items                  | 0.000071 |
| logging slow query             | 0.000002 |
| logging slow query             | 0.000058 |
| cleaning up                    | 0.000005 |
+--------------------------------+----------+

我已经在这个问题上研究了很长时间了,但一直没有找到解决方案。这个查询有什么明显的错误吗?我看不到查看420行应该花2秒钟以上的时间。


问题答案:

您正在通过主键访问420行,这可能会导致索引访问路径。每个键可以访问2个索引页和一个数据页。如果它们在缓存中,则查询应运行得很快。否则,对磁盘的每个页面访问都会产生通常的磁盘延迟。如果我们假设磁盘延迟为5毫秒,高速缓存命中率为80%,则得出的时间为420 * 3 * 0.2 * 5ms = 1.2秒,与您看到的顺序相同。



 类似资料:
  • 问题内容: 我正在执行以下查询 在field1上有一个索引,在field2&field3上有另一个索引。 我看到MySQL总是选择field1索引,然后使用其他两个字段进行联接,这很糟糕,因为它需要联接146.000行。 关于如何改善这一点的建议?谢谢 (在尝试解决方案后进行编辑) 基于提出的解决方案,我在使用此工具时已经在Mysql上看到了。 比执行慢很多: 具有两个复合索引: 足够有趣的是,要

  • 问题内容: 我懂了 “无效的列名daysdiff”。 Maxlogtm是日期时间字段。是让我发疯的小东西。 问题答案: 通常,您不能在子句中引用字段别名。(将其视为包括别名在内的全部内容,在该子句之后应用。) 但是,如其他答案所述,您可以强制将SQL视为在子句之前进行处理。通常使用圆括号来强制操作的逻辑顺序,或者使用通用表表达式(CTE)来完成此操作: 括号/子选择: 或参阅亚当的CTE版本答案。

  • 问题内容: 我有一个查询,看起来像: 尽管我对资源有索引,但它不使用它。如何优化将其用于按位运算。 问题答案: 我不认为MySQL可以使索引用于按位操作。 MySQLPerformance论坛中对此进行了一些讨论:http : //forums.mysql.com/read.php?24,35318(“按位比较可以进行索引扫描吗?”),MySQL员工根据每对(事物,设置位)对具有一行并进行一堆联接

  • 问题内容: 这行代码是我的select语句的摘录。 以下是我的where子句的摘录 我的问题是如何引用FreeDaysRemaining列,因此可以将其与@进行比较 我正在寻找这样的东西 问题答案: 除了Aaron的答案,您还可以使用公用表表达式:

  • 我创建了一个带有主键(UsersID、AccountsID)的帐户/用户表,如下所示。我是否应该为Users表添加索引?

  • 问题内容: 在用户属于特定组织的情况下,我们具有以下实体关系。我的查询看起来像是“从org =:org用户选择”或“从org =:org用户输入和type =:type选择” 我在User类上有单独的索引。由于外键元素上的索引,因此第一个查询会很好。第二个查询是否对组织和类型列要求多列索引。如果是这样,我应该如何注释以创建一个这样的索引。 问题答案: 使用hibernate特定注释可以做到这一点。