如何优化下一个免费"插槽的研究?在mysql中?

时间:2015-02-07 18:47:13

标签: mysql algorithm search subquery

我有一个问题,我找不到一个简单的解决方案。 我有这种自我扩展的结构。

database1 |表格1           |表2           ....           |表n

。 。

databaseN |表格1             表2             表n

每张桌子都有这样的结构:

ID |值

每次生成一个数字都被放入正确的数据库/表/结构中(以这种方式划分以实现可伸缩性......将无法以一种方式管理数十亿条记录表。)

N不固定的问题......但是就像计算数字的基础一样(确切地说,N是已知的...... 62但是我只能使用可能在时间上不同的“数字”子集)。

例如我只能使用0 1和2并且过了一段时间(当我完成所有可能性时)我想要添加4等等(直到62基础)。

我想找到一种简单的方法来找到第一个空闲插槽来放置下一个随机生成的ID但可以还原。

例:

我想要使用0 1 2 3作为数字....

元素2313放在dabase 2表3上,表格中有13 |值。

将元素1301放在dabase 1表3上,表格中将有01 |值。

我想根据下一个空闲时段生成另一个号码。 我可以测试从0到最大数字的每个槽,但是当每个数据库和表都有数百万条记录时,这是不可能的。

第一个例子的下一个元素是2323(而不是2314,因为我只使用了0 1 2 3个数字)。 我想在mysql中输入一些invers代码给我在表3数据库2上的23个插槽,将其转换为数字。我可以随机生成一个数字并尝试找到最近的自由上下,但由于该集合是变量不是一个好的选择。

我希望能明确告诉我任何建议; - )

1 个答案:

答案 0 :(得分:0)

使用

  • show databases like 'database%'以及查找不存在的数据库的循环
  • show tables like 'table%'和表格循环
  • select count(*) from tableN查看表格是否已满#34;或不。
  • 要查找空闲广告位,请使用count以数据块的形式遍历数据库。

这个未经测试的PHP / MySQL实现将在创建新表或数据库之前首先将所有现有数据库和表填充到基础N+1。 如果需要其他行为,则应更改if(!$base)部分。

findFreeChunk也可以通过迭代求解;但我把这种努力留给了你。

define (DB_PREFIX, 'database');
define (TABLE_PREFIX, 'table');
define (ID_LENGTH, 2)

function findFreeChunk($base, $db, $table, $prefix='')
{
    $maxRecordCount=base**(ID_LENGTH-strlen($prefix));
    for($i=-1; ++$i<$base;)
    {
        list($n) = mysql_fetch_row(mysql_query(
            "select count(*) from `$db`.`$table` where `id` like '"
            . ($tmp = $prefix. base_convert($i, 10, 62))
            . "%'"));
        if($n<$maxRecordCount)
        {
            // incomplete chunk found: recursion
            for($k=-1;++$k<$base;)
                if($ret = findFreeChunk($base, $db, $table, $tmp)
                { return $ret; }
        }
    }
}

function findFreeSlot($base=NULL)
{
    // find current base if not given
    if (!$base)
    {
        for($base=1; !$ret = findFreeSlot(++$base););
        return $ret;
    }

    $maxRecordCount=$base**ID_LENGTH;

    // walk existing DBs
    $res = mysql_query("show databases like '". DB_PREFIX. "%'");
    $dbs = array ();
    while (list($db)=mysql_fetch_row($res))
    {
        // walk existing tables
        $res2 = mysql_query("show tables in `$db` like '". TABLE_PREFIX. "%'");
        $tables = array ();
        while (list($table)=mysql_fetch_row($res2))
        {
            list($n) = mysql_fetch_row(mysql_query("select count(*) from `$db`.`$table`"));
            if($n<$maxRecordCount) { return findFreeChunk($base, $db, $table); }
            $tables[] = $table;
        }
        // no table with empty slot found: all available table names used?
        if(count($tables)<$base)
        {
            for($i=-1;in_array($tmp=TABLE_PREFIX. base_convert(++$i,10,62),$tables););
            if($i<$base) return [$db, $tmp, 0];
        }
        $dbs[] = $db;
    }
    // no database with empty slot found: all available database names used?
    if(count($dbs)<$base)
    {
        for($i=-1;in_array($tmp=DB_PREFIX.base_convert(++$i,10,62),$dbs););
        if($i<$base) return [$tmp, TABLE_PREFIX. 0, 0];
    }
    // none: return false
    return false;
}

如果您没有重复使用您的插槽或没有删除任何内容,您当然可以转储所有这些,只需记住最后一个ID来计算下一个ID。