MySQL “IN” operator performance on (large?) number of values

后端 未结 6 747
囚心锁ツ
囚心锁ツ 2020-11-28 03:26

I have been experimenting with Redis and MongoDB lately and it would seem that there are often cases where you would store an array of id\'s in either Mongo

6条回答
  •  萌比男神i
    2020-11-28 03:46

    I have been doing some tests, and as David Fells says in his answer, it is quite well optimized. As a reference, I have created an InnoDB table with 1,000,000 registers and doing a select with the "IN" operator with 500,000 random numbers, it takes only 2.5 seconds on my MAC; selecting only the even registers takes 0.5 seconds.

    The only problem that I had is that I had to increase the max_allowed_packet parameter from the my.cnf file. If not, a mysterious “MYSQL has gone away” error is generated.

    Here is the PHP code that I use to make the test:

    $NROWS =1000000;
    $SELECTED = 50;
    $NROWSINSERT =15000;
    
    $dsn="mysql:host=localhost;port=8889;dbname=testschema";
    $pdo = new PDO($dsn, "root", "root");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $pdo->exec("drop table if exists `uniclau`.`testtable`");
    $pdo->exec("CREATE  TABLE `testtable` (
            `id` INT NOT NULL ,
            `text` VARCHAR(45) NULL ,
            PRIMARY KEY (`id`) )");
    
    $before = microtime(true);
    
    $Values='';
    $SelValues='(';
    $c=0;
    for ($i=0; $i<$NROWS; $i++) {
        $r = rand(0,99);
        if ($c>0) $Values .= ",";
        $Values .= "( $i , 'This is value $i and r= $r')";
        if ($r<$SELECTED) {
            if ($SelValues!="(") $SelValues .= ",";
            $SelValues .= $i;
        }
        $c++;
    
        if (($c==100)||(($i==$NROWS-1)&&($c>0))) {
            $pdo->exec("INSERT INTO `testtable` VALUES $Values");
            $Values = "";
            $c=0;
        }
    }
    $SelValues .=')';
    echo "
    "; $after = microtime(true); echo "Insert execution time =" . ($after-$before) . "s
    "; $before = microtime(true); $sql = "SELECT count(*) FROM `testtable` WHERE id IN $SelValues"; $result = $pdo->prepare($sql); $after = microtime(true); echo "Prepare execution time =" . ($after-$before) . "s
    "; $before = microtime(true); $result->execute(); $c = $result->fetchColumn(); $after = microtime(true); echo "Random selection = $c Time execution time =" . ($after-$before) . "s
    "; $before = microtime(true); $sql = "SELECT count(*) FROM `testtable` WHERE id %2 = 1"; $result = $pdo->prepare($sql); $result->execute(); $c = $result->fetchColumn(); $after = microtime(true); echo "Pairs = $c Exdcution time=" . ($after-$before) . "s
    ";

    And the results:

    Insert execution time =35.2927210331s
    Prepare execution time =0.0161771774292s
    Random selection = 499102 Time execution time =2.40285992622s
    Pairs = 500000 Exdcution time=0.465420007706s
    

提交回复
热议问题