Рейтинг@Mail.ru

Журнал "Код моё имя" » Статьи блога » Статьи

Из Firebird/Interbase в My

(1 сообщение)
  1. Sergey
    Хранитель

    Кажется, что может быть проще перегона данных 1 к 1 из одной релятивной базы в другую? Просто делаеш селект из одной и инсерт в другую. Но тут возникает проблемма с тем, как выбрать например записи с 900 до 1000. Большенство програмистов сразу же предложат запрос SELECT FIRST 1000 SKIP 900 …. (так как в firebird нет LIMIT) и такой запрос выполнится очень быстро, но только при маленьких объёмах данных (до 1 млн. записей). А что делать в случае, если нам необходимо сделать выборку 10 последних строк из 10 000 000 записей? Такой запрос будет выполняться уже около 52 секунд.
    Как вы уже могли догадаться, есть и другой метод выборки записей – это выборка по индексу. В данной статье именно такой алгоритм я и хочу описать.

    Для подключения к базам данных воспользуемся стандартными регулярными выражениями php.
    Для работы нам понадобытся библиотеки php5-ibase и php5-mysql.
    Описание самого процесса перегона базы я вставлю в коментарии в коде скрипта.
    Предположим, что у нас есть 2 одинаковые по структуре базы данных firebird и mysql. они имеют одну таблицу с полнями
    id, key, value где в обеих таблицах на поля кинуты индексы а на поле key кинут уникальный индекс. Таблицу назовём my_tbl
    Вот пример кода:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    <?php
    ini_set('disply_error', E_ALL);

    //Сначала зададим параметры баз данных согласто документации
    $fb_host = 'localhost:база';
    $fb_username='SYSDBA';
    $fb_password='пароль';
    $mysql_host = 'localhost';
    $mysql_username='root';
    $mysql_password='пароль';
    $mysql_db='база';

    // далее нам необходимо подключиться к базам данных

    $dbh = ibase_connect ( $fb_host, $fb_username, $fb_password ) or die ("Firebird умер");
    $dbm = mysql_connect ( $mysql_host,$mysql_username,$mysql_password) or die("MySQL умерла");
    $tr = ibase_trans (IBASE_NOWAIT, IBASE_READ, IBASE_CONCURRENCY, $dbh);
    //выбираем БД и кодировку символов. Обратите внимание, на то, что в фаербёде
    //база данных выбирается иначе чем в mysql, в фаербёде она указывается при
    //открытии стэка(подключении)
    mysql_select_db($mysql_db);
    mysql_query("SET NAMES 'cp1251'");

    //подсчитаем общее количество записей в исходной БД
    $stmt = 'select count(*) from my_tbl';
    $sth = ibase_query($dbh, $stmt);
    while ($row = ibase_fetch_assoc($sth))
        {
        $count = intval($row['COUNT']) ;
        }

    //теперь нам нужно соответственно установить начальное и конечное положение индекса
    //так как мы будем выбирать с нуля то $mincnt будет равно 0
    $mincnt=0;

    //определяем максимальное число уникальных строк
    $stmt = 'select max(key) from my_tbl';
    $sth = ibase_query($dbh, $stmt);
    while ($row = ibase_fetch_assoc($sth))
        {
        $maxcnt = intval($row['MAX']);
        }
    $cnt=$mincnt;
    $rcnt=0; $rcnts=0;

    //начинаем переборку записей и выборку из индекса по 50000 записей вставляя их в mysql
    while ($rcnts<$count)
        {
        $stmt = 'select count(*) from my_tbl where key BETWEEN (' .$cnt. ') AND (' .($cnt+49999). ') ';
        $sth = ibase_query($tr,$stmt);
        while ($row = ibase_fetch_assoc($sth))
        {
        $rcnt = intval($row['COUNT']);
        }
       
        $stmt = 'SELECT * FROM  my_tbl WHERE key BETWEEN (' .$cnt. ') AND (' .($cnt+49999). ') ORDER BY key';
        $sth = ibase_query($tr, $stmt);
     

    Обратите внимание на то, как осушествляется перебор по индексу. мы берём из индекса кусками строки и потом генерируем обин пакет из общего числа строк. Кстати, запрос $stmt = ‘SELECT * FROM my_tbl WHERE key BETWEEN (‘ .$cnt. ‘) AND (‘ .($cnt+49999). ‘) ORDER BY key’; может вернуть нам не обязательно 50 000 строк, именно по этому мы и делаем проверку циклом while ($rcnts<$count) то есть итерации будут происходить до тех пор, пока количество выбранных из индекса строк не достигнет общего количества строк.

    Данный способ является наиболее эфективным и быстродейственным. По сравнительным результатам вариант конвертирования через first x skip y на 10 000 000 записей занял бы неделю, а написанный мною вариант конвертирует базу за 30 минут и соответственно эфективнее первого метода в 336 раз.
    Из Firebird/Interbase в MySQL

    Отправлено 7 месяцев назад #

RSS экспорт этой темы

Отправить сообщение

Вы должны войти в систему, чтобы оставлять сообщения.