1. 程式人生 > >100w測試資料,為什麼加了索引查詢反而變慢了?

100w測試資料,為什麼加了索引查詢反而變慢了?

建表:
create table tb_test(fval varchar(50));
----------------------------------------------
插入測試資料:
DELIMITER $$

CREATE DEFINER=`root`@`localhost` PROCEDURE `P_teset`()
BEGIN
        DECLARE v_val VARCHAR(20);
DECLARE v_str VARCHAR(20);
        DECLARE v_i INT ;
        DECLARE v_j INT;	

SET v_str ='abcdefghijklmnopqrstuvwxyz';
        SET v_i=0;
        SET v_j=0;
        
        WHILE v_i<600000 DO 
           SET v_val ='';
           
           WHILE v_j< 13 DO 
              SET v_val= CONCAT(v_val,SUBSTRING(v_str,1,FLOOR(1+RAND()*26)));               
              SET v_j=v_j+1;           
           END WHILE;
           SET v_j=0;
           INSERT INTO tb_test(fval)
           VALUES(v_val);     

           SET v_i =v_i+1;              
        END WHILE;
    END$$

DELIMITER ;
----------------------------------------------
測試like:

SELECT *
FROM tb_test 
WHERE fval LIKE '%ab';

70231條 用時0.531s

SELECT *
FROM tb_test 
WHERE fval LIKE 'ab%'

961406條用時1.422s
---------------------------------------------
加索引:
ALTER TABLE tb_test ADD INDEX  my_index(fval); 
---------------------------------------------
再測試:
SELECT *
FROM tb_test 
WHERE fval LIKE '%ab';

70231條 用時1.094s

SELECT *
FROM tb_test 
WHERE fval LIKE 'ab%'

961406條用時1.485s

表為MyISAM格式。

為什麼加了索引卻慢了?
SELECT *
FROM tb_test  
WHERE fval LIKE '%ab';

70231條 用時0.531s

SELECT *
FROM tb_test  
WHERE fval LIKE 'ab%'
 961406條用時1.422s



select * 本身輸出也需要時間,第二個查詢的結果是 961406 條,而第一個是70231條. 需要考慮這麼多記錄本身的輸出顯示到螢幕上所需要時間。

可以測試

select count(*) FROM tb_test  WHERE fval LIKE '%ab';
select count(*) FROM tb_test WHERE fval LIKE 'ab%'

建表:
create table tb_test(fval varchar(50));
----------------------------------------------
插入測試資料:
DELIMITER $$

CREATE DEFINER=`root`@`localhost` PROCEDURE `P_teset`()
BEGIN
  DECLARE v_val V……



幾個知識點:
1:like '%ab',這樣萬用字元在左邊的,MYSQL是不會用到索引的,MYSQL使用索引用的是最左字首的方式。
2:like 'ab%',這樣可能用到索引,你需要在查詢語句前面加EXPLAIN關鍵字看看是否用到了索引。
3:檢查一個SQL的效率是否變化了,需要排除出QUERY_CACHE,在查詢時這樣寫
select sql_no_cache * from ... where ...這樣就不會從QUERY_CACHE取資料了。多執行幾次取平均值比較靠譜。