Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MySQL > MySql + обновление индекса


Автор: Artemon 9.7.2008, 06:24
Использую MySql 5.*

В одной из таблиц определен индекс по числовому полю, но постепенно при вставках данных - этот индекс разбалтывается и разбалтывается на столько, что с БД невозможно работать - запросы занимают несколько минут (с индексом пару секунд), так вот как можно автоматически пересчитывать индексы к пимеру каждый день ?


Автор: skyboy 9.7.2008, 07:06
Цитата(Artemon @  9.7.2008,  05:24 Найти цитируемый пост)
этот индекс разбалтывается

может, пояснишь, что ты имеешь в виду? художественніе примемы зороши только не в ущерб смыслу

Автор: Feldmarschall 9.7.2008, 08:33
Artemon, твое понимание смысла индексов оставляет желать лучшего. 
И твои предположения о причинах задержек неверны. 

поэтому задавая вопрос, как тебе ускорить тот или иной запрос, следует писать только две вещи:
1. сам запрос
2. вывод  EXPLAIN с этим запросом.
(если бы кто-нибудь когда-нибудь читал правила, то я бы предложил внести это в правила форума.)

Автор: Artemon 9.7.2008, 09:49
Что я понимаю под словом "разболтался" - в таблицу были добавлены новые данные и индекс необходимо пересчитать.

Цитата

И твои предположения о причинах задержек неверны. 


Всетаки я думаю мои предположения верны, объясню.
В бд постоянно добавляются новые записи (примерно 1 запись в секунду круглосуточно).
Постепенно запросы к БД начинают выполняться медленнее, после того, как я сношу индекс и создаю его заново - все нормализуется, поэтому я и предположил что индекс нужно постоянно пересчитывать.

А запросы большие и сложные, но если кто-то посмотрит на них и прокомментирует - буду рад.

Код

DELIMITER $$

DROP PROCEDURE IF EXISTS `LOCARUS`.`Get_DATA` $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `Get_DATA`(
IN _IMEI nvarchar(50),
IN _SERIAL_COMPUTER_NUMBER nvarchar(50),
OUT _Ret bigint,
IN _StartID bigint
)
BEGIN
    declare _MyMax bigint;

    SELECT max(DATA.ID_DATA) INTO _Ret FROM DATA
    INNER JOIN DEVICES ON DEVICES.ID_DEVICE = DATA.ID_DEVICE
    WHERE IMEI_NAME = _IMEI;

       SELECT _Ret;
    

    SELECT MAX(POINTER)  INTO _MyMax FROM SERIALS 
    INNER JOIN DEVICES ON DEVICES.ID_DEVICE = SERIALS.ID_DEVICE
    INNER JOIN SERIAL_LIST ON SERIAL_LIST.ID_SERIAL_LIST = SERIALS.ID_SERIAL_LIST
    WHERE IMEI_NAME = _IMEI
    AND SERIAL = _SERIAL_COMPUTER_NUMBER;
    
    

        IF EXISTS
            ( 
            SELECT DEVICES.ID_DEVICE FROM DEVICES
                    INNER JOIN SERIALS ON SERIALS.ID_DEVICE = DEVICES.ID_DEVICE
                    INNER JOIN SERIAL_LIST ON SERIAL_LIST.ID_SERIAL_LIST = SERIALS.ID_SERIAL_LIST
            WHERE SERIAL = _SERIAL_COMPUTER_NUMBER 
            AND IMEI_NAME = _IMEI 
            LIMIT 1
            )        
            THEN
                SELECT DATA_SIZE,DATA, ID_DATA
                FROM DATA
                INNER JOIN DEVICES ON DATA.ID_DEVICE = DEVICES.ID_DEVICE 
                INNER JOIN SERIALS ON SERIALS.ID_DEVICE = DEVICES.ID_DEVICE
                INNER JOIN SERIAL_LIST ON SERIAL_LIST.ID_SERIAL_LIST = SERIALS.ID_SERIAL_LIST
                WHERE
                    (
                    DATA.ID_DATA > _MyMax
                    )
                AND SERIAL = _SERIAL_COMPUTER_NUMBER 
                AND IMEI_NAME = _IMEI
                AND DATA.ID_DATA <= _Ret
                AND DATA.ID_DATA > _StartID
                ORDER BY ID_DATA
                LIMIT 1000
                ;
            ELSE
                SELECT DATA_SIZE,DATA, ID_DATA
                FROM DATA 
                INNER JOIN DEVICES ON DATA.ID_DEVICE = DEVICES.ID_DEVICE 
                AND IMEI_NAME = _IMEI
                AND DATA.ID_DATA <= _Ret
                AND DATA.ID_DATA > _StartID
                ORDER BY ID_DATA
                LIMIT 1000
                ;
            END IF;

END $$

DELIMITER ;

Автор: Feldmarschall 9.7.2008, 10:10
Индекс так устроен, что он сам перестраивается. не "раз в день", а после каждой вставки, его затрагивающей.
А запрос и правда забавный.

Автор: MuToGeN 13.7.2008, 09:15
Feldmarschall, есть исключение - mysqld любит рушить индексы, когда приходится работать с действительно объемными базами.
Из своей практики: ISPшная биллинговая система, таблица, хранящая в себе логи трафика, кто что скачал. Таблица обновляется раз в минуту. Без вырубания mysqld для оптимизации таблиц, myisamchk и прочего оно успешно кладется само по себе.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)