Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Mysql. Много данных. Нужна оптимизация [2]

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (2): « 1 [2]   

> Без описания
Panoptik
Отправлено: 22 Октября, 2014 - 16:54:48
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2493
Дата рег-ции: Нояб. 2011  
Откуда: Одесса, Украина


Помог: 131 раз(а)




фигня какая-то происходит
запросы возвращают 0
при этом именно этот запрос
Мелкий пишет:
Как себя ведёт запрос
CODE (SQL):
скопировать код в буфер обмена
SELECT count(0)
FROM `apple_store_top` `t`
WHERE (platform="1")
  AND (appId=:ycp0) AND (country=:ycp1) AND (category=:ycp2)
выполняется быстро и говорит 0
а чуть проще
говорит так
PHP:
скопировать код в буфер обмена
  1. mysql> SELECT count(id) FROM `apple_store_top` `t` WHERE (platform="1")   AND (appId=499200558);
  2. +-----------+
  3. | count(id) |
  4. +-----------+
  5. |         0 |
  6. +-----------+
  7. 1 row in set, 1 warning (31.79 sec)
  8.  

(Добавление)
подозреваю что с партицированием я что-то натворил и пока не поздно покажу как я сделал чтобы изменить пока данные не пошли в оборот

CODE (SQL):
скопировать код в буфер обмена
  1. PARTITION BY HASH (( YEAR(`created`)*100 + MONTH(`created`) )) PARTITIONS 96

(Добавление)
нашлась причина, просчитался я с размером поля для appId. mediumint мне не хватило и тут пошли жалобы
Message: Out of range value for column 'appId' at row 1


-----
Just do it
 
 Top
Мелкий Супермодератор
Отправлено: 22 Октября, 2014 - 17:08:40
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Да, что-то не то.
Там должна быть портянка вроде такой:
CODE (SQL):
скопировать код в буфер обмена
  1. /*!50100 PARTITION BY RANGE ( EXTRACT(YEAR_MONTH FROM `date`))
  2. (PARTITION p201401 VALUES LESS THAN (201401) ENGINE = InnoDB,
  3.  PARTITION p201402 VALUES LESS THAN (201402) ENGINE = InnoDB,
  4.  PARTITION p201403 VALUES LESS THAN (201403) ENGINE = InnoDB,
  5. -- и так насколько вас хватит, лет на 10-20 вперёд
  6.  PARTITION pMAXVALUE VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */;
  7.  


Но сначала характер нагрузки. Быть может, вам надо партицировать не по дате, а по другим признакам. Что надо чаще получать? Вернее, по какому признаку можно отсекать больше всего данных?


Васин друган пишет:
память все же там не настолько критична как скорость дисков

Верно, не критична. Но больше памяти - меньше требуется от дисков.


-----
PostgreSQL DBA
 
 Top
Васин друган
Отправлено: 22 Октября, 2014 - 17:10:17
Post Id


Новичок


Покинул форум
Сообщений всего: 8
Дата рег-ции: Окт. 2014  


Помог: 0 раз(а)




Panoptik пишет:
DATE_FORMAT(created, "%Y.%m.%d%H:00") created

вот это бы убрать бы, лучше потом сверху обернуть. субд не надо тратиться на преобразование в длинных таблицах

(Отредактировано автором: 22 Октября, 2014 - 17:12:37)

 
 Top
Panoptik
Отправлено: 22 Октября, 2014 - 17:19:02
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2493
Дата рег-ции: Нояб. 2011  
Откуда: Одесса, Украина


Помог: 131 раз(а)




уберу, но не думаю что проблема в этом, раньше нормально работало. короче сейчас данные я запорол, нужно ждать пока отбекапится. завтра буду продолжать колдовать
(Добавление)
Мелкий пишет:
Но сначала характер нагрузки. Быть может, вам надо партицировать не по дате, а по другим признакам. Что надо чаще получать? Вернее, по какому признаку можно отсекать больше всего данных?
пока данные выбираются все, это примерно за 3-4 недели, но в запросах предполагается выборка за последних 30 дней в основном, так что думаю что партицирование по дате будет справедливо
(Добавление)
Васин друган пишет:
прошу прощения, что встреваю. предыдущие подсказки (Мелкий) абсолютно верны. судя по условиям, основная нагрузка идет по полю криетед. проиндексировав его Вы должны почувствовать разницу. и кантри я бы убрал в отдельную таблицу и вязал бы через айдишники, исключив строковую обработку полей. country in ['aa','bb','ss'] - не хорошо. другое дело насколько проблематично будет перелопатить коды приложения, если они уже привязаны к структуре имеющейся.
и третье, периодическое развертывание бэкапа - тоже будет полезно, файлы бд будут более монолитнее.


приложение пока только строится, так что все уже переделал под внешние таблицы и числовые значения

текущая таблица имеет такую структуру

CODE (SQL):
скопировать код в буфер обмена
  1. CREATE TABLE `apple_store_top` (
  2.   `id` bigint(20) NOT NULL AUTO_INCREMENT,
  3.   `appId` int(11) NOT NULL,
  4.   `position` smallint(4) UNSIGNED NOT NULL,
  5.   `country` tinyint(3) UNSIGNED NOT NULL,
  6.   `category` tinyint(3) UNSIGNED NOT NULL,
  7.   `platform` tinyint(2) UNSIGNED NOT NULL,
  8.   `created` datetime NOT NULL,
  9.   `type` tinyint(1) UNSIGNED NOT NULL,
  10.   PRIMARY KEY (`id`,`created`),
  11.   KEY `i_ccp_ast2` (`country`,`category`,`platform`),
  12.   KEY `i_cat_ast2` (`category`),
  13.   KEY `i_appId_ast2` (`appId`),
  14.   KEY `i_country_created_ast2` (`country`,`created`),
  15.   KEY `i_created_ast2` (`created`),
  16.   KEY `i_position_ast2` (`position`)
  17. ) ENGINE=InnoDB AUTO_INCREMENT=16765529 DEFAULT CHARSET=utf8
  18. /*!50100 PARTITION BY RANGE ( EXTRACT(YEAR_MONTH FROM `date`))
  19. (PARTITION p201409 VALUES LESS THAN (201409) ENGINE = InnoDB
  20. .....
  21. PARTITION p202512 VALUES LESS THAN (202512) ENGINE = InnoDB
  22. PARTITION pMAXVALUE VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */
  23.  


-----
Just do it
 
 Top
Dastor
Отправлено: 22 Октября, 2014 - 17:52:38
Post Id


Гость


Покинул форум
Сообщений всего: 66
Дата рег-ции: Окт. 2014  


Помог: 3 раз(а)




Интересно, а будет ли разница во времени выполнения, если в фильтрации убрать кавычки и поменять местами условия?

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT count(id) FROM `apple_store_top` `t` WHERE (appId=499200558) AND (platform=1);
 
 Top
Panoptik
Отправлено: 22 Октября, 2014 - 18:00:57
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2493
Дата рег-ции: Нояб. 2011  
Откуда: Одесса, Украина


Помог: 131 раз(а)




вряд ли, оптимизатор делает в фоне много преобразований и подбирает условия как ему удобнее


-----
Just do it
 
 Top
MiksIr
Отправлено: 22 Октября, 2014 - 18:46:38
Post Id


Забанен


Покинул форум
Сообщений всего: 378
Дата рег-ции: Сент. 2014  


Помог: 10 раз(а)

[+]


Васин друган пишет:
что касается ресурсов сервера бд, память все же там не настолько критична как скорость дисков. на своей шкуре почувствовал (оракл порядка 300 млн записей).

Ну так партицирование как раз и позволяет решить этот вопрос с дисками.


-----
self-banned
 
 Top
Васин друган
Отправлено: 23 Октября, 2014 - 06:25:02
Post Id


Новичок


Покинул форум
Сообщений всего: 8
Дата рег-ции: Окт. 2014  


Помог: 0 раз(а)




ну, тогда вот честно - что-то не догоняю. не спорю, секционирование ранжирование никто не отменял.
а память? Имеется в виду кэширование результатов запросов? или ? .. дальше боюсь сморозить фигню какю-нибудь. смотрю на скрипты, вроде ничего военного не вижу.
 
 Top
Мелкий Супермодератор
Отправлено: 23 Октября, 2014 - 10:07:35
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




Васин друган пишет:
а память? Имеется в виду кэширование результатов запросов? или ?

Это относится вот сюда, правильно понимаю?
Мелкий пишет:
Верно, не критична. Но больше памяти - меньше требуется от дисков.


Память, любое количество памяти, утилизируется под кэш данных и индексов. Кеширование результатов - это могли додуматься только в mysql. У нормальных БД - кэширование плана запроса после оптимизатора (который далеко не за бесплатно работает).
Данные живут в: кеш непосредственно СУБД (очень быстрый и дешёвый), затем кэш страниц операционной системы (чуть медленнее, но тоже дешёвый) и потом обращение к дискам (очень медленно и очень дорого)
Оперировать СУБД может только с данными, размещёнными в собственном кэше. Соответственно, если там нет нужных данных - СУБД просит ОС эти данные прочитать (вот на это "просит" требуется некоторое время, в отличии от собственного кеша, потому не так быстро и дёшево). ОС может вернуть данные из своего кеша или читать с дисков.

Ужасный вариант - в память (имеется в виду кэш СУБД или ОС) не влезают даже индексы, тупой index scan - и тот читает с дисков. Читать с дисков очень дорого, так что ничего хорошего из этого не получится, тормозить будут даже смехотворные запросы по покрывающим индексам на таблицах в никчёмные десятки тысяч строк. Утилизировать на 100% можно любой диск самой незначительной табличкой.
Индексы в памяти, прогрета часть рабочих данных - что-то размещено в памяти, но на весь рабочий набор памяти не хватило - постоянно с дисков вычитываются новые данные, старые вытесняются из памяти. Распространённый вариант. Тут как раз нужно многое от дисков. Зависит от отношения объёма рабочих данных к объёму памяти под кеши, чем больше данных поднято с дисков в кеш - тем меньше требуется читать с дисков.
Отличный вариант - все рабочие данные размещены в памяти, диски только пишут новые данные и очень редко читают (кому-то вдруг исторические данные поглядеть захотелось). А типичная нагрузка веб-приложения - больше 90% чтения, вот от дисков почти ничего особого и не требуется, от них зависит только скорость записи (ну и время на чтение всего этого при старте системы). Вот тут уже реально упереться в CPU, ну или в сеть, т.к. диски не ограничивают производительность чтения.


-----
PostgreSQL DBA
 
 Top
Васин друган
Отправлено: 23 Октября, 2014 - 15:55:14
Post Id


Новичок


Покинул форум
Сообщений всего: 8
Дата рег-ции: Окт. 2014  


Помог: 0 раз(а)




вот так просветили! не ожидал. спасибо). но так глубоко мне не добраться. странно, а я почему-то отталкивался от транзакционных систем. еще вчера язык чесался, что не надо такие запросы запускать. и если проект еще не боевой, лучше заранее сагрегировать что-нибудь под олапы кубики.
 
 Top
Stierus Супермодератор
Отправлено: 24 Октября, 2014 - 16:38:24
Post Id



Рекордсмен по количеству сообщений за 7 дней


Покинул форум
Сообщений всего: 2132
Дата рег-ции: Дек. 2008  
Откуда: Москваль


Помог: 52 раз(а)




i_category_store_top - ненужный ключ, его можно смело удалить

Конструкция

SELECT
appId,
count(appId) cnt,
....
GROUP BY appId,

мне вообще не понятна, что вы хотите при этом получить?

скиньте дамп строк в 100к что бы статистику примерную видеть
(Добавление)
GROUP BY DATE_FORMAT(created, "%Y.%m.%d %H:00") Этот запрос сразу отрубает у вас работу с индексами.

Now () в условии из первого запроса убивает всю работу с кэшами

Что бы решить эти проблемы - организуйте доп поле системное, которое будет хранить уже обработанную DATE_FORMAT(created, "%Y.%m.%d %H:00") строку, либо ее хэш (если коллизии для вас не критичны), а из условий уберите now(), заменив их полученными в php готовыми значениями
 
My status
 Top
Страниц (2): « 1 [2]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Работа с СУБД »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB