16.03.2010, 15:26 | #1 |
Участник
|
Оптимизация запросов к БД в коде
----------------
sukhanchik Обсуждение вынесено из ветки Нужен совет: Oracle или MS SQL ---------------- 5 лет назад я говорил, что "таких нет", кто будет выбирать в пользу MS SQL. Теперь я изменил свое мнение. Работаю на базе данных MS SQL с 9 млн. проводок и 448 тыс. накладных. Никаких блокировок и тормозов нет. Все летает. Размер базы 150 ГБ. Не парюсь со всякими хинтами типа forceplaceholders и forcenestedloops. Везде использую exist join - очень удобно. Чтобы база работала быстро, надо: 1) Большое количество памяти на сервере, чтобы информацию о блокировках записей SQL-сервер целиком помещал в памяти. Тогда не будет возникать страничных и табличных блокировок. 2) периодически перестраивать индексы и обновлять статистику запросов 3) программисту всегда проверять, есть ли индекс по полям, которые перечислены в выражении отбора "where". достаточно иметь индекс по первому полю, идущему в выражении отбора "where" 3)в выражении отбора "where" сначала перечислять более уникальные поля, а потом менее уникальные - например надо писать "where inventTrans.TransRefId == 'journalId' && inventTrans.TransType == InventTransType.InventTransfer". А так писать нельзя: "where inventTrans.TransType == InventTransType.InventTransfer && inventTrans.TransRefId == 'journalId' ". Последний раз редактировалось sukhanchik; 17.03.2010 в 16:59. |
|
|
За это сообщение автора поблагодарили: hated8 (1). |
16.03.2010, 15:46 | #2 |
Участник
|
Цитата:
Сообщение от Ace of Database
3)в выражении отбора "where" сначала перечислять более уникальные поля, а потом менее уникальные - например надо писать "where inventTrans.TransRefId == 'journalId' && inventTrans.TransType == InventTransType.InventTransfer". А так писать нельзя: "where inventTrans.TransType == InventTransType.InventTransfer && inventTrans.TransRefId == 'journalId' ".
|
|
16.03.2010, 16:26 | #3 |
Участник
|
Цитата:
Сообщение от fed
Я не уверен что ее лечить надо. Я просто начинал работать на Informix, дык вот там когда место в таблице блокировок кончалось (при массовых обновлениях), просто генерировалась ошибка и транзакция откатывалась. В MS SQL за счет эскалации эта проблема преврашается в несколько менее тяжелую - проблему конфликтов из за страничных блокировок. В оракле проблема исчерпания таблицы блокировок не возникает, поскольку информация о блокировках храниться собственно в страницах БД. Однако такой способ хранения информации о блокировках чреват некоторым падением производительности при работе с блокировками.
Так что: а) не факт что надо лечить б) не факт что побочные эффекты от лекарства не окажуться тяжелее болезни. Реально конечно нужно смотреть схожие по объемы и числу активных сессий инсталляции и сравнивать. |
|
16.03.2010, 16:33 | #4 |
Участник
|
Абсолютно серьезно. Много таких мест переделал, когда возникали тормоза - менял местами поля в условии. Я сугубо практик, не теоретик. База медленно работает тогда, когда программисты не следят за тем, что у них в условии "where" написано. По более уникальному полю SQL-сервер сразу отсекает кучу ненужной информации.
В приведенном мною примере сервер быстро найдет складские проводки по коду журнала - их всего несколько десятков штук, а затем из этих нескольких десятков проводок выберет те, у которых тип - "Перенос". А если написать запрос наоборот, то сервер сначала будет искать все проводки с типом "Перенос" - их могут быть миллиноны. |
|
16.03.2010, 16:51 | #5 |
Участник
|
|
|
16.03.2010, 17:10 | #6 |
Участник
|
Цитата:
3)в выражении отбора "where" сначала перечислять более уникальные поля, а потом менее уникальные - например надо писать "where inventTrans.TransRefId == 'journalId' && inventTrans.TransType == InventTransType.InventTransfer". А так писать нельзя: "where inventTrans.TransType == InventTransType.InventTransfer && inventTrans.TransRefId == 'journalId' ".
Неадекватное поведение могло быть связано с неактуальной статистикой, но никак не с порядком критериев в where. |
|
16.03.2010, 17:25 | #7 |
----------------
|
Раз человек говорит, значит у него так и было и перестановка where помогла.
Только я подозреваю, что проблема не в where, а в последующем order by, который построен по этим же полям и включается соответствующей галкой. и в целом, можно только за их компанию порадоваться Цитата:
Работаю на базе данных MS SQL с 9 млн. проводок и 448 тыс. накладных. Никаких блокировок и тормозов нет. Все летает. Размер базы 150 ГБ.
Не парюсь со всякими хинтами типа forceplaceholders и forcenestedloops. |
|
16.03.2010, 17:53 | #8 |
Участник
|
Вы наверное испытывате желание подловить меня на чем-то? То, что я предлагаю, работает лишь на сложных запросах. Найти стандартный пример я вам не могу, т.к. это зависит от многих условий, и на разных базах один и тот же запрос будет работать очень быстро или очень медленно.
Вот недавно оптимизированный в моей базе запрос, который зависал. Запрос до оптимизации PHP код:
Запрос после оптимизации PHP код:
|
|
|
За это сообщение автора поблагодарили: Logger (3). |
16.03.2010, 17:57 | #9 |
Участник
|
И мне непонятно желание подкольнуть меня. Неужто я что-то вредное предлагаю? Неужто внимательное написание запросов - это вредный совет? И неужто для вас так важно, вы так хотите не соблюдать порядок полей в условиях?
Последний раз редактировалось Ace of Database; 16.03.2010 в 18:01. |
|
16.03.2010, 18:00 | #10 |
Участник
|
Намеренно оставил в комментариях кода //group by TableId .
Просто у нас тут тоже были спорщики, которые утверждали, что exists join тормозит. И пытались ускорить путем устранения exist join'а. Пока не переставил местами поля в условиях отбора, ничего не помогало |
|
16.03.2010, 18:01 | #11 |
Участник
|
Цитата:
Если все именно так и есть как вы говорите, то я сильно разочаруюсь в MS SQL |
|
16.03.2010, 18:41 | #12 |
Участник
|
Цитата:
Сообщение от Ace of Database
5 лет назад я говорил, что "таких нет", кто будет выбирать в пользу MS SQL. Теперь я изменил свое мнение.
Работаю на базе данных MS SQL с 9 млн. проводок и 448 тыс. накладных. Никаких блокировок и тормозов нет. Все летает. Размер базы 150 ГБ. Не парюсь со всякими хинтами типа forceplaceholders и forcenestedloops. Везде использую exist join - очень удобно. Еще, конечно, очень интересно было бы узнать про чей-нибудь опыт использования сжатия данных в Ms SQL 2008: по-моему, когда данные на диске сжимаются в разы, это должно как-то очень существенно повлиять на стратегии оптимизации запросов и различные весовые коэффициенты, в них используемые. |
|
16.03.2010, 18:48 | #13 |
Участник
|
|
|
16.03.2010, 18:49 | #14 |
Участник
|
Цитата:
P.S.: А как вы представляете себе соблюдение 'оптимальной' последовательности условий при конструировании запроса при помощи Query? |
|
16.03.2010, 19:03 | #15 |
Участник
|
Цитата:
Сообщение от gl00mie
Вы бы хоть рассказали, какая используется версия Ms SQL (2005/2008), используется ли сжатие, если речь о 2008-м, какое у вас железо - очень было бы интересно это узнать. Потому что с точки зрения DBA, возможно, все и однозначно: лучше Oracle, потому что там больше настроек, потому что там есть RAC, потому что его можно поставить на (чей-нибудь любимый) *nix и все такое. Но с точки зрения компании в контексте TCO, по-моему, все не так однозначно: железо дешевеет и при этом становится мощнее и шустрее, а специалисты по ораклу, во-первых, "не растут на деревьях", а во-вторых, как отмечалось, "стоят типа дорого".
Еще, конечно, очень интересно было бы узнать про чей-нибудь опыт использования сжатия данных в Ms SQL 2008: по-моему, когда данные на диске сжимаются в разы, это должно как-то очень существенно повлиять на стратегии оптимизации запросов и различные весовые коэффициенты, в них используемые. Здесь я попытался акцентировать внимание на том, что от программирования очень много зависит - не меньше чем от железа. Запрос, который я здесь привел, выполнялся за 2 секунды до оптимизации. Но так как он вызывался столько раз, сколько строк в закупке, то система висела по несколько минут. После оптимизации закупки открываются моментально, независимо от количества строк в них. И я не в коем случае не говорю, что MS SQL лучше, чем Oracle! Просто, MS SQL тоже пригоден для работы с большими объемами данных. Забыл сказать: версия SQL - 2005 Последний раз редактировалось Ace of Database; 16.03.2010 в 19:16. |
|
16.03.2010, 19:07 | #16 |
Участник
|
Цитата:
Сообщение от S.Kuskov
Ничего личного. Стратегия оптимизации логична и ясна. Просто необходимость проделывать её вручную ствится под сомнение. Нужно подобрать хороший пример и провести исследование данного вопроса.
P.S.: А как вы представляете себе соблюдение 'оптимальной' последовательности условий при конструировании запроса при помощи Query? |
|
16.03.2010, 19:12 | #17 |
Участник
|
Ну хотя бы сколько памяти на сервере БД вы можете сказать ?
|
|
16.03.2010, 19:21 | #18 |
Участник
|
Завтра скажу
|
|
16.03.2010, 19:21 | #19 |
Участник
|
Согласен, с Query есть свои проблемы, но при желании их можно обойти. Помогите с Query
|
|
16.03.2010, 22:53 | #20 |
NavAx
|
Вероятнее всего проблема с изменением порядка полей и последующим ускорением/замедлением запросов лежит в плоскости оптимизатора аксапты, а не sql. В dax3 с какого-то kr оптимизатор аксапты начал сам подставлят индексы в запросы согласно условиям where.
|
|
Теги |
index hint, sql server, оптимизация |
|
Похожие темы | ||||
Тема | Ответов | |||
Параметры запросов БД | 3 | |||
Владельцы таблиц в БД аксапты | 11 | |||
Оптимизация запросов | 6 | |||
Оптимизация запросов | 3 | |||
Просмотр SQL запросов к БД с помощью файла Log | 3 |
|