索引顺序扫描引发的heap scan IO放大, 背后的统计学原理与解决办法

标签

PostgreSQL , 优化器 , 索引扫描 , 堆扫描 , IO放大


背景

通过B-TREE索引扫描可能会带来了巨大的heap page scan数目,即IO的放大.

为什么呢?

请接下去看完本文揭晓答案。

IO放大的后果:

如果数据库的单个数据块(block_size)很大的话, 这种情况带来的负面影响也将被放大. 例如32k的block_size显然比8k的block_size扫描开销更大.

本文将讲解一下索引扫描引发的heap page scan放大的原因, 以及解决办法。 告诫大家注意这样的事情发生,以及如何对付。

正文

测试环境的成本因子如下 :

shared_buffers = 8192MB                 # min 128kB
#seq_page_cost = 1.0                    # measured on an arbitrary scale
random_page_cost = 1.0                  # same scale as above
#cpu_tuple_cost = 0.01                  # same scale as above
cpu_index_tuple_cost = 0.005            # same scale as above
#cpu_operator_cost = 0.0025             # same scale as above
effective_cache_size = 96GB

我们先创建一个测试表, 插入一些测试数据, 创建一个索引 :

digoal=> create table test_indexscan(id int, info text);
CREATE TABLE
digoal=> insert into test_indexscan select generate_series(1,5000000),md5(random()::text);
INSERT 0 5000000
digoal=> create index idx_test_indexscan_id on test_indexscan (id);
CREATE INDEX

我们查看这个表和索引占用了多少数据块.

digoal=> select relpages from pg_class where relname='test_indexscan';
 relpages
----------
    10396
(1 row)
digoal=> select relpages from pg_class where relname='idx_test_indexscan_id';
 relpages
----------
     3402
(1 row)

接下来分析以下查询, 我们看到走索引扫描, 并且扫描的数据块是13547个. (10209 +3338).

扫描的数据块和实际表占用的数据块和索引块相当.

digoal=> explain (analyze,verbose,costs,buffers,timing) select * from test_indexscan where id>90000;
                                                                           QUERY PLAN                                                 

------------------------------------------------------------------------------------------------------------------------------------
-----------------------------
 Index Scan using idx_test_indexscan_id on digoal.test_indexscan  (cost=0.43..99518.57 rows=4912065 width=37) (actual time=0.180..21
72.949 rows=4910000 loops=1)
   Output: id, info
   Index Cond: (test_indexscan.id > 90000)
   Buffers: shared hit=10209 read=3338
 Total runtime: 2674.637 ms
(5 rows)

这里使用索引扫描为什么没有带来heap page扫描的放大呢? 原因和值的顺序与物理存储顺序一致.

如下, 那么索引扫描的时候没有发生块的跳跃 :

digoal=> select correlation from pg_stats where tablename='test_indexscan' and attname='id';
 correlation
-------------
  1
(1 row)
digoal=> select ctid,id from test_indexscan limit 10;
  ctid  |   id
--------+---------
 (0,1)  | 1
 (0,2)  | 2
 (0,3)  | 3
 (0,4)  | 4
 (0,5)  | 5
 (0,6)  | 6
 (0,7)  | 7
 (0,8)  | 8
 (0,9)  | 9
 (0,10) | 10
(10 rows)

接下来我们插入随机数据, 使得索引扫描时发生heap page的跳跃.

digoal=> truncate test_indexscan ;
TRUNCATE TABLE
digoal=> insert into test_indexscan select (random()*5000000)::int,md5(random()::text) from generate_series(1,100000);
INSERT 0 100000

查询当前的ID列的顺性, 非常小, 说明这个值非常的离散.

digoal=> select correlation from pg_stats where tablename='test_indexscan' and attname='id';
 correlation
-------------
  0.00986802
(1 row)

从数据分布结果中也能看到这点.

digoal=> select ctid,id from test_indexscan limit 10;
  ctid  |   id
--------+---------
 (0,1)  | 4217216
 (0,2)  | 2127868
 (0,3)  | 2072952
 (0,4)  |   62641
 (0,5)  | 4927312
 (0,6)  | 3000894
 (0,7)  | 2799439
 (0,8)  | 4165217
 (0,9)  | 2446438
 (0,10) | 2835211
(10 rows)

按以下顺序扫描, 显然会出现大量的数据块的跳跃.

digoal=> select id,ctid from test_indexscan order by id limit 10;
 id  |   ctid
-----+-----------
  56 | (192,318)
  73 | (119,163)
 218 | (189,2)
 235 | (7,209)
 260 | (41,427)
 340 | (37,371)
 548 | (118,363)
 607 | (143,174)
 690 | (161,38)
 714 | (1,21)
(10 rows)

当前这个表和索引占用的数据块如下 :

digoal=> select relpages from pg_class where relname='test_indexscan';
 relpages
----------
      208
(1 row)  

digoal=> select relpages from pg_class where relname='idx_test_indexscan_id';
 relpages
----------
       86
(1 row)

接下来我们执行这个SQL, 发现走索引扫描了, 但是显然shared hit变得非常的大, 原因就是每扫描一个索引条目, 对应到heap page number都是跳跃的. 造成了heap page扫描的放大. 具体放大多少行呢, 和差出来的行差不多.

digoal=> explain (analyze,verbose,costs,buffers,timing) select * from test_indexscan where id>90000;
                                                                        QUERY PLAN                                                    

------------------------------------------------------------------------------------------------------------------------------------
----------------------
 Index Scan using idx_test_indexscan_id on digoal.test_indexscan  (cost=0.29..2035.38 rows=99719 width=37) (actual time=0.027..87.45
6 rows=98229 loops=1)
   Output: id, info
   Index Cond: (test_indexscan.id > 90000)
   Buffers: shared hit=97837
 Total runtime: 97.370 ms
(5 rows)

heap page scan放大评估和索引扫描了多少条目有关, 但至少有98229个条目 :

digoal=> select count(*) from test_indexscan where id>90000;
 count
-------
 98229
(1 row)

如果纯随机扫描, 那么将要扫描98229次heap page. 也就不难理解这里的Buffers: shared hit=97837.

但是实际上, PostgreSQL的优化器似乎没有关注这些开销, 因为我们看到的成本只有2035.38 (这里和random_page_cost以及effective_cache_size 大于整个表和索引的空间有关)

接下来把random_page_cost设置为2和1, 两个cost相减, 看看到底优化器评估了多少个块扫描.

digoal=> set random_page_cost=2;
SET
digoal=> set enable_seqscan=off;
SET
digoal=> explain (analyze,verbose,costs,buffers,timing) select * from test_indexscan where id>90000;
                                                                        QUERY PLAN                                                    

------------------------------------------------------------------------------------------------------------------------------------
----------------------
 Index Scan using idx_test_indexscan_id on digoal.test_indexscan  (cost=0.29..2305.73 rows=98255 width=37) (actual time=0.045..81.76
8 rows=98229 loops=1)
   Output: id, info
   Index Cond: (test_indexscan.id > 90000)
   Buffers: shared hit=97837
 Total runtime: 92.186 ms
(5 rows)  

digoal=> set random_page_cost=1;
SET
digoal=> explain (analyze,verbose,costs,buffers,timing) select * from test_indexscan where id>90000;
                                                                        QUERY PLAN                                                    

------------------------------------------------------------------------------------------------------------------------------------
----------------------
 Index Scan using idx_test_indexscan_id on digoal.test_indexscan  (cost=0.29..2012.75 rows=98255 width=37) (actual time=0.028..80.05
5 rows=98229 loops=1)
   Output: id, info
   Index Cond: (test_indexscan.id > 90000)
   Buffers: shared hit=97837
 Total runtime: 90.549 ms
(5 rows)

相减得到293, 即优化器认为index scan需要扫描293个数据块.

digoal=> select 2305-2012;
 ?column?
----------
      293
(1 row)

接下来我把enable_indexscan关闭, 让优化器选择bitmap scan.

digoal=> set enable_indexscan=off;
SET
digoal=> explain (analyze,verbose,costs,buffers,timing) select * from test_indexscan where id>90000;
                                                                QUERY PLAN                                                            

------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on digoal.test_indexscan  (cost=846.77..2282.96 rows=98255 width=37) (actual time=15.291..35.911 rows=98229 loops=
1)
   Output: id, info
   Recheck Cond: (test_indexscan.id > 90000)
   Buffers: shared hit=292
   ->  Bitmap Index Scan on idx_test_indexscan_id  (cost=0.00..822.21 rows=98255 width=0) (actual time=15.202..15.202 rows=98229 loo
ps=1)
         Index Cond: (test_indexscan.id > 90000)
         Buffers: shared hit=84
 Total runtime: 45.838 ms
(8 rows)

从bitmap scan的结果可以看到, 实际扫描的块为292个, 相比index scan少扫描了9.7万多数据块. 并且实际的执行时间也是bitmap scan要快很多.

本例PostgreSQL在计算index scan的random page的成本时, 评估得到的index scan成本小于bitmap index scan的成本, 然而实际上当correlation 很小时, index scan会扫描更多次的heap page, 成本远远大于bitmap scan.

本例发生这样的情况, 具体的原因和我们的成本因子设置有关系, 因为错误的设置了random_page_cost以及表和索引的大小小于effective_cache_size, PostgreSQL在使用这样的成本因子计算成本时, 出现了bitmap scan大于index scan成本的结果.

所以设置正确的成本因子非常重要, 这也是我们需要校准成本因子的原因.

例子 :

[postgres@digoal pgdata]$ psql
psql (9.3.4)
Type "help" for help.

默认的成本因子如下

digoal=# show seq_page_cost;
 seq_page_cost
---------------
 1
(1 row)  

digoal=# show random_page_cost;
 random_page_cost
------------------
 4
(1 row)  

digoal=# show cpu_tuple_cost;
 cpu_tuple_cost
----------------
 0.01
(1 row)  

digoal=# show cpu_index_tuple_cost;
 cpu_index_tuple_cost
----------------------
 0.005
(1 row)  

digoal=# show cpu_operator_cost;
 cpu_operator_cost
-------------------
 0.0025
(1 row)  

digoal=# show effective_cache_size;
 effective_cache_size
----------------------
 128MB
(1 row)

表和索引的大小如下

digoal=# \dt+ tbl_cost_align
                         List of relations
 Schema |      Name      | Type  |  Owner   |  Size  | Description
--------+----------------+-------+----------+--------+-------------
 public | tbl_cost_align | table | postgres | 219 MB |
(1 row)  

digoal=# \di+ tbl_cost_align_id
                                  List of relations
 Schema |       Name        | Type  |  Owner   |     Table      | Size  | Description
--------+-------------------+-------+----------+----------------+-------+-------------
 public | tbl_cost_align_id | index | postgres | tbl_cost_align | 64 MB |
(1 row)

把random_page_cost校准为10, 这个在一般的硬件环境中都适用.

digoal=# set random_page_cost=10;
SET

默认选择了全表扫描

digoal=# explain (analyze,costs,buffers,timing,verbose) select * from tbl_cost_align where id>2000000;
                                                            QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------
 Seq Scan on public.tbl_cost_align  (cost=0.00..65538.00 rows=2996963 width=45) (actual time=0.050..1477.028 rows=2997015 loops=1)
   Output: id, info, crt_time
   Filter: (tbl_cost_align.id > 2000000)
   Rows Removed by Filter: 2985
   Buffers: shared hit=28038
 Total runtime: 2011.742 ms
(6 rows)

关闭全表扫描后, 选择了bitmap scan

digoal=# set enable_seqscan=off;
SET
digoal=# explain (analyze,costs,buffers,timing,verbose) select * from tbl_cost_align where id>2000000;
                                                                     QUERY PLAN                                                       

------------------------------------------------------------------------------------------------------------------------------------
----------------
 Bitmap Heap Scan on public.tbl_cost_align  (cost=105426.89..170926.93 rows=2996963 width=45) (actual time=1221.104..2911.889 rows=2
997015 loops=1)
   Output: id, info, crt_time
   Recheck Cond: (tbl_cost_align.id > 2000000)
   Rows Removed by Index Recheck: 2105
   Buffers: shared hit=36229
   ->  Bitmap Index Scan on tbl_cost_align_id  (cost=0.00..104677.65 rows=2996963 width=0) (actual time=1214.865..1214.865 rows=2997
015 loops=1)
         Index Cond: (tbl_cost_align.id > 2000000)
         Buffers: shared hit=8191
 Total runtime: 3585.699 ms
(9 rows)

关闭bitmap scan后选择了index scan, index scan的cost远远大于评估到的bitmap scan. 因为我们使用了正确的成本因子.

digoal=# set enable_bitmapscan=off;
SET
digoal=# explain (analyze,costs,buffers,timing,verbose) select * from tbl_cost_align where id>2000000;
                                                                           QUERY PLAN                                                 

------------------------------------------------------------------------------------------------------------------------------------
----------------------------
 Index Scan using tbl_cost_align_id on public.tbl_cost_align  (cost=0.43..16601388.04 rows=2996963 width=45) (actual time=0.064..566
2.361 rows=2997015 loops=1)
   Output: id, info, crt_time
   Index Cond: (tbl_cost_align.id > 2000000)
   Buffers: shared hit=3005084
 Total runtime: 6173.067 ms
(5 rows)

当错误的设置了random_page_cost=1=seq_page_cost时, 执行计划会有所改变(改变出现在effective_cache_size大于表和索引的大小时).

the wrong plan cost occur when i set random_page_cost to 1, and effective_cache_size big then index size and table size in this case.

重新进入psql, 所有因子重回默认值.

digoal=# set random_page_cost=1;
SET
digoal=# explain (analyze,costs,buffers,timing,verbose) select * from tbl_cost_align where id>2000000;
                                                            QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------
 Seq Scan on public.tbl_cost_align  (cost=0.00..65538.00 rows=2996963 width=45) (actual time=0.040..1692.712 rows=2997015 loops=1)
   Output: id, info, crt_time
   Filter: (tbl_cost_align.id > 2000000)
   Rows Removed by Filter: 2985
   Buffers: shared hit=28038
 Total runtime: 2249.313 ms
(6 rows)

目前看来还正确

digoal=# set enable_seqscan=off;
SET
digoal=# explain (analyze,costs,buffers,timing,verbose) select * from tbl_cost_align where id>2000000;
                                                                    QUERY PLAN                                                        

------------------------------------------------------------------------------------------------------------------------------------
--------------
 Bitmap Heap Scan on public.tbl_cost_align  (cost=31446.89..96946.93 rows=2996963 width=45) (actual time=1224.445..2454.797 rows=299
7015 loops=1)
   Output: id, info, crt_time
   Recheck Cond: (tbl_cost_align.id > 2000000)
   Rows Removed by Index Recheck: 2105
   Buffers: shared hit=36229
   ->  Bitmap Index Scan on tbl_cost_align_id  (cost=0.00..30697.65 rows=2996963 width=0) (actual time=1220.404..1220.404 rows=29970
15 loops=1)
         Index Cond: (tbl_cost_align.id > 2000000)
         Buffers: shared hit=8191
 Total runtime: 2955.816 ms
(9 rows)

当effective_cache_size还是小于表和索引时, 执行计划依旧正确

digoal=# set effective_cache_size='280MB';
SET
digoal=# explain (analyze,costs,buffers,timing,verbose) select * from tbl_cost_align where id>2000000;
                                                                   QUERY PLAN                                                         

------------------------------------------------------------------------------------------------------------------------------------
-------------
 Bitmap Heap Scan on public.tbl_cost_align  (cost=31446.89..96946.93 rows=2996963 width=45) (actual time=963.845..2060.463 rows=2997
015 loops=1)
   Output: id, info, crt_time
   Recheck Cond: (tbl_cost_align.id > 2000000)
   Rows Removed by Index Recheck: 2105
   Buffers: shared hit=36229
   ->  Bitmap Index Scan on tbl_cost_align_id  (cost=0.00..30697.65 rows=2996963 width=0) (actual time=959.673..959.673 rows=2997015
 loops=1)
         Index Cond: (tbl_cost_align.id > 2000000)
         Buffers: shared hit=8191
 Total runtime: 2515.649 ms
(9 rows)

当effective_cache_size大于表和索引的大小时, index scan的成本低于bitmap scan的成本了.

When effective_cache_size large then table and index's size. then use index scan first than bitmap scan.
digoal=# set effective_cache_size='283MB';
SET
digoal=# explain (analyze,costs,buffers,timing,verbose) select * from tbl_cost_align where id>2000000;
                                                                         QUERY PLAN                                                   

------------------------------------------------------------------------------------------------------------------------------------
-------------------------
 Index Scan using tbl_cost_align_id on public.tbl_cost_align  (cost=0.43..92030.24 rows=2996963 width=45) (actual time=0.045..5238.3
61 rows=2997015 loops=1)
   Output: id, info, crt_time
   Index Cond: (tbl_cost_align.id > 2000000)
   Buffers: shared hit=3005084
 Total runtime: 5689.583 ms
(5 rows)

如果这个时候再把random_page_cost调回正常值10, 则执行计划回归正常.

digoal=# set random_page_cost=10;
SET
digoal=# explain (analyze,costs,buffers,timing,verbose) select * from tbl_cost_align where id>2000000;
                                                                    QUERY PLAN                                                        

------------------------------------------------------------------------------------------------------------------------------------
---------------
 Bitmap Heap Scan on public.tbl_cost_align  (cost=105426.89..170926.93 rows=2996963 width=45) (actual time=918.225..2195.414 rows=29
97015 loops=1)
   Output: id, info, crt_time
   Recheck Cond: (tbl_cost_align.id > 2000000)
   Rows Removed by Index Recheck: 2105
   Buffers: shared hit=36229
   ->  Bitmap Index Scan on tbl_cost_align_id  (cost=0.00..104677.65 rows=2996963 width=0) (actual time=913.935..913.935 rows=299701
5 loops=1)
         Index Cond: (tbl_cost_align.id > 2000000)
         Buffers: shared hit=8191
 Total runtime: 2698.429 ms
(9 rows)  

digoal=# set enable_seqscan=on;
SET
digoal=# explain (analyze,costs,buffers,timing,verbose) select * from tbl_cost_align where id>2000000;
                                                            QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------
 Seq Scan on public.tbl_cost_align  (cost=0.00..65538.00 rows=2996963 width=45) (actual time=0.020..1522.791 rows=2997015 loops=1)
   Output: id, info, crt_time
   Filter: (tbl_cost_align.id > 2000000)
   Rows Removed by Filter: 2985
   Buffers: shared hit=28038
 Total runtime: 2104.057 ms
(6 rows)

本例说明了成本因子的重要性. 千万不能随意设置, 即使完全内存命中, random_page_cost也应该大于seq_page_cost.

我在前一篇BLOG中测试了这样的场景, 完全内存命中的场景可以设置 random_page_cost=1.6; seq_page_cost=1;

《优化器成本因子校对 - PostgreSQL explain cost constants alignment to timestamp》

B-TREE扫描,对于线性相关性不好的列,会放大HEAP SCAN 的IO消耗,使用bitmap可以解决。

线性相关性的知识如下

《PostgreSQL 计算 任意类型 字段之间的线性相关性》

《PostgreSQL 统计信息之 - 逻辑与物理存储的线性相关性》

小结

1. 当字段的存储与值线性相关性差时,使用index scan会导致大量的HEAP SCAN IO放大。

2. bitmap index scan巧妙的解决了放大的问题,bitmap index scan对index item按照ctid(heap行号)排序后再取数据,避免了单个HEAP PAGE的重复IO。

3. 使用cluster对heap数据按索引顺序进行重排,也可以解决HEAP SCAN IO放大的问题。

参考

1. http://www.postgresql.org/message-id/flat/13668.1398541533@sss.pgh.pa.us#13668.1398541533@sss.pgh.pa.us

2. 《优化器成本因子校对 - PostgreSQL explain cost constants alignment to timestamp》

3. src/backend/optimizer/path/costsize.c

cost_index function :
        /*
         * Now interpolate based on estimated index order correlation to get total
         * disk I/O cost for main table accesses.
         */
        csquared = indexCorrelation * indexCorrelation;  

        run_cost += max_IO_cost + csquared * (min_IO_cost - max_IO_cost);  
时间: 2024-10-27 19:27:24

索引顺序扫描引发的heap scan IO放大, 背后的统计学原理与解决办法的相关文章

oracle点知识6——索引跳跃式扫描

以下内容整理自网络: 索引跳跃式扫描(index skip scan)是Oracle9i用来提高性能的新特性,对于使用复合索引的数据库应用程序意义尤为重大. 复合索引(又称为连接索引)是一个包含多个字段的索引.在ORACLE9i以前的ORACLE版本里,只有那些在WHERE子句里引用整个索引或者是引用索引的一个或多个前导字段的查询,才能使复合索引有效而提高检索效率.而在ORACLE9i里,一个复合索引即使在一次查询中没有使用前导字段,也可能通过"索引跳跃式扫描"被有效引用(比如有两个字

textbox-C# 索引超出了数组界限 论坛找过了 没有找到答案 求解决!

问题描述 C# 索引超出了数组界限 论坛找过了 没有找到答案 求解决! if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) { int i = 0; string Path = folderBrowserDialog1.SelectedPath; string[] filepath = System.IO.Directory.GetFiles(Path); string[] filename = new string[1000];

串口硬盘数据线引发的系统故障及解决办法

第一代串口硬盘数据线往往固定不牢,容易松动,从而引发意想不到的系统故障,笔者就曾经遇到过这种情况,下面一探讨解决办法. 步骤/方法 串口硬盘有这样那样的优点且发展潜力巨大,于是逐渐取代了并口硬盘;然而开始生产的串口硬盘的数据线十分容易松动,往往拔插几次后,基本上就很难插牢了,松动了常常引发出一些问题.如果你是电脑高手,也容易辨别,但经常如此也让人烦;如果你对电脑有关知识知知甚少,那就摸不着头脑了. 当串口硬盘数据线松了后,硬盘灯还是亮的,系统变得极为绶慢,每进行一步操作,很久才有反应,让人无法忍

使用HttpURLConnection下载文件时出现 java.io.FileNotFoundException彻底解决办法

使用HttpURLConnection下载文件时经常会出现 java.io.FileNotFoundException文件找不到异常,下面介绍下解决办法 首先设置tomcat对get数据的编码:conf/server.xml <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncodin

此OracleParameterCollection 的 Count=4 的索引 4 无效 的解决办法 NHibernate

概述:      当用Nhibernate操作主从表时,往主表插入数据时,当执行到提交事务时出现如下错误: 此 OracleParameterCollection 的 Count=4 的索引 4 无效. 在 System.Data.OracleClient.OracleParameterCollection.RangeCheck(Int32 index) 在 System.Data.OracleClient.OracleParameterCollection.GetParameter(Int32

Android扫描二维码时出现用户禁止权限报错问题解决办法

Android扫描二维码时出现用户禁止权限报错问题解决办法 当我用ZBarDecoder.jar写了一个扫描二维码的程序,确实实现了扫描功能.组长说如果用户禁止调用摄像头,那程序也不能崩溃.结果我一运行就崩溃了.在网上自己找了找,可以这样解决. try { mCameraManager.openDriver(); } catch (Exception e) { //当用户手动禁止摄像头权限时,防止系统崩溃 AlertDialog.Builder builder=new AlertDialog.B

为JS扩展Array.prototype.indexOf引发的问题及解决办法_基础知识

Array没有indexOf方法,这样在一个数组中查找某个元素的索引时比较麻烦,为了调用方便,于是通过prototype原型扩展了Array.prototype.indexOf(),这样用起来就比较方便了.但是这个自定义的indexOf在对数组进行遍历的时候却出现了问题. 复制代码 代码如下: Array.prototype.indexOf = function(item) {  for (var i = 0; i < this.length; i++) {  if (this[i] == it

Windows7系统扫描并修复可移动磁盘后U盘内文件丢失的解决办法

  此时会有两个选择: 1.扫描并修复(推荐) 2.继续,但不要扫描 万分警告 在确定你U盘里面有重要资料时千万不能点第一个选项:扫描并修复(推荐) 虽然提示:这将防止以后将文件复制到此设备或光盘时出现问题,但是你也是确保你U盘里面的资料无关紧要时再扫扫描并修复. 选择扫描并修复的后果 U盘有些资料会丢失,有些文件会损坏. 取而代之的你会发现自己的U盘里多一个文件夹(在显示隐藏文件及系统文件下可以看到)FOUND.000,此文件夹里有若干个类似FILE0000.chk文件(数量视情况而定),文件

mysql占用CPU过高的解决办法(添加索引)_Mysql

下面是MYSQL占用CPU高处理的一个例子,希望对遇到类似问题的朋友们有点启发.一般来说MYQL占用CPU高,多半是数据库查询代码问题,查询数据库过多.所以一方面要精简代码,另一方面最好对频繁使用的代码设置索引. 今天早上起来 机器报警 一查负载一直都在4以上 top了一下 发现 mysql 稳居 第一 而且相当稳定 我擦 重启一下mysql不行 mysql> show processlist;一下 发现xxx网站有两条 查询语句 一直 在列,我擦 该站 也就30多万条记录 量也不大 不可能是机