Оптимизация производительности SQL является большой проблемой для программистов, потому что мы часто сталкиваемся с этой проблемой: когда мы разрабатываем проект, мы чувствуем, что функциональный опыт его самостоятельного тестирования действительно хорош, но после запуска реального проекта, с огромным увеличением Согласно данным, качество обслуживания клиентов системы становится все хуже и хуже. Конечно, помимо фреймворка и неразумного кода, основная причина в том, что SQL не был оптимизирован, из-за чего система стала работать всё медленнее и медленнее.
Поскольку я работаю в небольшой компании, то делаю все, думаю, что иногда лучше лечить симптомы, чем лечить первопричину! Есть несколько вопросов, на которые следует обратить внимание:
1. Дизайн таблицы базы данных должен быть разумным, особенно дизайн первичного ключа. Если объем данных в таблице очень велик, дизайн первичного ключа не должен быть значимым, как и ROWID, например, ROWID. GUID SQL Server, UUID Hibernate и т. д. Конечно, некоторые таблицы словаря данных можно гибко обрабатывать, и нет необходимости считать, что они должны быть физическими первичными ключами. При разработке первичного ключа составные первичные ключи обычно не используются.
2. Разумная индексация. Индекс — мощный инструмент и хорошее средство для ускорения запроса данных. Но не добавляйте каждое поле. Принцип индексации аналогичен оглавлению книги. Если оглавление вашей книги почти все имеет одно и то же название, вы можете себе представить следующее: насколько быстро вы сможете найти конкретное содержание по оглавлению. ? Индекс не обязательно должен быть уникальным, но в нем не должно быть слишком много одинаковых записей. Кроме того, если добавить больше индексов, табличное пространство TEMP увеличится. При экспорте таблицы и ее импорте в другую базу данных индексы также снизят эффективность импорта. В это время вы также обнаружите, что табличное пространство UNDOTBS01. является аномально большим. Таким образом, индекс – это палка о двух концах, и его следует применять разумно.
3. Я видел в Интернете несколько очень профессиональных статей об оптимизации SQL, но чувствую, что не смог использовать их в своем проекте. Вместо этого я продолжал экспериментировать и открывать некоторые основные принципы в ходе проекта. Лично я считаю, что существует только один принцип оптимизации SQL: максимально сузить область запроса. Это определенно повысит эффективность, и Oracle сама может оптимизировать SQL, который мы пишем, поэтому нам нужно это сделать. максимально сузьте область запроса. Говоря об этом, я думаю, каждый обязательно подумает, что индексирование — это мощный инструмент для повышения скорости запроса. Действительно, это всего лишь средство, и оно также вытекает из принципа сужения области запроса. .
Большая часть SQL, которую необходимо оптимизировать, — это запросы на соединение нескольких таблиц, а соединения нескольких таблиц также включают горизонтальные и вертикальные соединения. Чаще всего мы используем вертикальные соединения. Горизонтальное соединение обычно означает, что структуры полей двух таблиц в основном одинаковы, и некоторые записи данных одной таблицы должны быть заменены некоторыми записями другой таблицы, то есть Строки+Строки. Вертикальное соединение означает, что мы берем некоторые поля для запроса из таблицы A и некоторые поля для запроса из таблицы B, а затем соединяем таблицы, вынесенные из таблиц A и B, вертикально, используя общую часть, то есть Столбцы+Столбцы.
Оператор горизонтального соединения: выберите a.column1,a.column2 из таблицы A объединение всех, выберите b.column1,b.column2 из таблицы B b
Обратите внимание, что при горизонтальном соединении количество столбцов должно быть одинаковым, а типы данных соответствующих столбцов полей должны быть одинаковыми. Фактически, вы можете думать об объединяемых таблицах как об одной копии другой, совершенно одинаковой. Кто-то может спросить: если столбцы, которые я хочу объединить, имеют разные столбцы или столбца вообще нет, то вы можете использовать следующий метод.
выберите d.dname,d.loc из dept1 d Union all выберите '' dname, e.loc из dept e, посмотрите "'' dname", мы легко обнаружим, что вы можете найти замену, вместо этого используйте пустую строку Там полей нет, поэтому их можно объединить.
Оператор вертикального соединения: выберите a.column1,a.column2 из таблицы A полное внешнее соединение, выберите b.column3,b.column4 из таблицы B b на a.aid=b.bid где..., это формат полного внешнего соединения. Эта скорость действительно очень высокая, но запрос может вам не понравиться, поскольку есть некоторые строки результатов, которые вы, возможно, вообще не захотите видеть. В обычных обстоятельствах мы чаще используем левое внешнее соединение и правое внешнее соединение. Разница между ними заключается в том, что левое внешнее соединение в основном основано на таблице, соответствующей полю соединения слева после включения, а правое внешнее соединение является противоположным. Конечно, вы также можете использовать левое и правое соединение. Во время использования я все же обнаружил, что внешние соединения работают относительно быстрее.
Чтобы повысить эффективность запросов на вертикальные соединения, можно вложить запросы. Ниже приведен реальный пример из проекта:
выберите c.customerid, c.receivedmoney, c.tollcollector, c.receiveddate, c.yearmonth, c.receivedlatefee,
c.receivedfee,c.receivedappend,c.jmman,c.jmmoney,c.name,d.chargeint от
(выберите идентификатор клиента, полученные деньги, сборщика дорожных сборов, дату получения, год-месяц, полученную плату за просрочку,
a.полученная плата,a.полученное приложение,a.jmman,a.jmmoney,b.имя из
(выберите rf.customerid,rf.receivedmoney,rf.tollcollector,rf.receiveddate,rf.годмесяц,rf.receivedlatefee,
rf.receivedfee,rf.receivedappend,rf.jmman,rf.jmmoney из sf_receivedfee rf где
rf.electriccompanyid='1000000001' и rf.dealsign=0 и rf.yearmonth in(200811,200901,200903,200804,200805,200806,200807)
и rf.customerid=1000052545) левое внешнее соединение (выберите xe.employeeid,xe.name из xt_employee xe) b на a.tollcollector=b.employeeid)
c левое внешнее соединение (выберите cp.chargeint,cp.customerid из sf_chargeprotocol cp, где cp.customerid=1000052545) d
на c.customerid=d.customerid
Вы можете видеть, что в этом примере мы сначала отфильтровываем нужные нам записи из каждой таблицы, используя почти одинаковые условия, а затем объединяем записи. В реальных условиях я обнаружил, что это почти в 60 раз быстрее, чем запрос прямой ссылки. Хотя он уродлив и труден для чтения, он решает проблему производительности SQL. Принцип, который он использует, по-прежнему заключается в том, чтобы сначала сузить область действия, а затем выполнить запрос на соединение. Если мы подключаемся, а затем фильтруем, это эквивалентно объединению двух таблиц, а затем выборке данных на основе условий. Скорость можно себе представить.