Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Дело в том, что на каждую строку из таблицы Table1 производится выборка «SELECT MAX(Column) FROM Table2», что требует дополнительных ресурсов для
новой выборки.
Необходимость использования LEFT JOIN, что во многих СУБД не работают индексы.
Есть ситуации, когда в условии объединения необходимо использовать дополнительные операции над полем, в таком случае индекс не используется [...] Возможные варианты решения: 1. Вынести в условие WHERE, но этот вариант не всегда даст положительный результат, т.к. за вас это мог сделать оптимизатор.
Разделить запрос на два.
Проблему можно решить, прибегая к временным таблицам, т.е. результат тяжелого запроса предварительно положить во временную таблицу и далее использовать.
Речь пойдёт о том, как облегчить рутинную работу поддержки и сопровождения баз данных.
приходится в обновлениях постоянно контролировать DROP-ы, ALTER-ы и т.д. в каждой СУБД по разному.
Запросы с использованием With
Стоимость создания/удаления временной таблицы вы не учитываете?
результат тяжелого запросапри этом стоимость создания временной таблицы несущественна, да и результат может быть незначительным.
А то, что в ней нет индексов?для временной таблицы всегда можно создать индекс даже в MSSQL.
Использованием адекватных инструментов
EXEC DropProcedure('SchemaName', 'ProcedureName1');
EXEC DropProcedure('SchemaName', 'ProcedureName2');
EXEC DropProcedure('SchemaName', 'ProcedureName3');
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'ProcedureName1')
DROP PROCEDURE ProcedureName1;
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'ProcedureName2')
DROP PROCEDURE ProcedureName2;
IF EXISTS (SELECT * FROM sys.objects WHERE type = 'P' AND name = 'ProcedureName3')
DROP PROCEDURE ProcedureName3;
COMMENT ON TABLE Schema.Table IS 'Комментарий таблицы';
COMMENT ON COLUMN Schema.Table.Column IS 'Комментарий колонки';
COMMENT ON PROCEDURE Schema.ProcedureName IS 'Комментарий процедуры';
при этом стоимость создания временной таблицы несущественна, да и результат может быть незначительным.
для временной таблицы всегда можно создать индекс даже в MSSQL.
речь о них в посте и не велась, но я таких не встречал, обычно это какие-нибудь неповоротливые комбайны, которые на первый взгляд что-то умеют, а на деле ничего хорошего.
На мой взгляд нет ничего лучше самописного редактора с засветкой таблиц, процедур, функций и с возможностью не закрывать транзакцию.
самописного
По поводу сервисных процедур, на мой взгляд запись вида [...] смотрится намного информативней и короче, чем [...]
по поводу комментирования таблиц и процедур мой вариант очевидно лучше, чем предлагает MSSQL,
NIH?, обёртки, IDEТеперь понятно к чему вы клоните, но я предпочитаю пользоваться удобными инструментами даже, если приходится их делать самому.
Теперь понятно к чему вы клоните, но я предпочитаю пользоваться удобными инструментами даже, если приходится их делать самому.
Не понятна цена замусоривания серверов сервисными процедурами, когда их от силы с пол сотни, а процедур отвечающих за бизнес логику порядка полутора тысящ.
Проблему можно решить, прибегая к временным таблицам, т.е. результат тяжелого запроса предварительно положить во временную таблицу и далее использовать.
SELECT M.Id, P1.Sum
FROM MainTable M
JOIN PayTable1 P1 ON P1.Id = M.Id
UNION
SELECT M.Id, P2.Sum
FROM MainTable M
JOIN PayTable2 P2 ON P2.Id = M.Id
SELECT
T.Column1,
T2.Column3,
T.Column2
FROM Table1 T
JOIN (SELECT Max(Column) as Column3 FROM Table2) T2 ON 1 = 1
ON 1 = 1. С таким условием у вас T2.Column3 будет всегда одинаковым. Впрочем в «не кошерном» варианте ситуация такая же. А в MS SQL нельзя вот так?SELECT
T.Column1,
MAX(T2.Column) AS Column3,
T.Column2
FROM Table1 T
JOIN Table2 T2 ON T2.T_id = T.id
GROUP BY T.Column1, T.Column2
SELECT
--Шапка отчёта
--где UserInfo вьюха, которая выдаёт данные о пользователе который запускает запрос
(SELECT FIO FROM UserInfo) as FIO,
(SELECT PhoneNumber FROM UserInfo) as PhoneNumber,
(SELECT Address FROM UserInfo) as Address,
--Данные отчёта
T.Column1, T.Column2, T.Column3
FROM Table1 T
SELECT U.FIO, U.PhoneNumber, U.Address, T.Column1, T.Column2, T.Column3
FROM Table1 T
JOIN UserInfo U ON 1 = 1
SELECT U.FIO, U.PhoneNumber, U.Address, T.Column1, T.Column2, T.Column3
FROM Table1 T, UserInfo U
на сервере есть таблица с информацией о пользователе.
Клиент тонкий, его цель в данном случае:
— отдать идентификатор отчёта и какие либо параметры, если требуется
Отчётных форм тысячи, и контролировать их на клиенте проблематично
информацию можно формировать на клиенте
обрабатывать информацию о пользователе и его действиях в среднем слое
Выносить механизм истории изменений в средний слой (бизнес логики), тоже нехорошо, т.к. он к ней отношения не имеет,
Да и если найдётся специалист, который имеет доступ править данные непосредственно в базе сведения об этом тоже необходимо фиксировать.
SELECT U.FIO, U.PhoneNumber, U.Address, T.Column1, T.Column2, T.Column3
FROM Table1 T
JOIN UserInfo U ON 1 = 1
SELECT
(SELECT FIO FROM UserInfo) as FIO,
(SELECT PhoneNumber FROM UserInfo) as PhoneNumber,
(SELECT Address FROM UserInfo) as Address,
T.Column1, T.Column2, T.Column3
FROM Table1 T
JOIN UserInfo U ON 1 = 1 какое-то странное.ON 1=1 без лимитов, то выборка будет состоять из 1 000 000 000 000 (1 триллион) строк.--где UserInfo вьюха, которая выдаёт данные о пользователе который запускает запрос
Стандартная функция, для MS SQL это SUSER_NAME(), для IBM DB2 USER()
Замена Left Join на UnionКак эти подходы можно сравнивать? Ведь схема выборки изменится!
SELECT
T1.*, T2.*
FROM Table1 T1
JOIN Table2 T2 ON T2.Id = T1.Id AND COALESCE(T2.Column, 0) = COALESCE(T1.Column, 0)
и SELECT
T1.*, T2.*
FROM Table1 T1
JOIN Table2 T2 ON T2.Id = T1.Id
WHERE COALESCE(T2.Column, 0) = COALESCE(T1.Column, 0)
COALESCE(T2.Column, 0) = COALESCE(T1.Column, 0) «искалось» по индексу — нужно создать для этого функциональные индексы.SELECT
T1.*, T2.*
FROM Table1 T1
JOIN Table2 T2 ON T2.Id = T1.Id AND T2.Column = T1.Column
UNION
SELECT
T1.*, T2.*
FROM Table1 T1
JOIN Table2 T2 ON T2.Id = T1.Id AND T2.Column IS NULL AND T1.Column IS NULL
будет более ресурсоёмким по сравнению с вариантом выше и функциональными индексами. Посмотрите сами на план запроса.Проблема в том, что многие думают, что подзапрос SubQuery выполнится один раз, и далее будет браться только результат и подставляется там, где он далее потребуется.
INSERT Session.MainSubQuery
SELECT * FROM Table1;
INSERT Session.SubQuery
SELECT * FROM Table2;
SELECT *
FROM Session.MainSubQuery M
LEFT JOIN Session.SubQuery Q1 ON Q1.id = M.id AND Q1.Param = 1
LEFT JOIN Session.SubQuery Q2 ON Q2.id = M.id AND Q2.Param = 2
LEFT JOIN Session.SubQuery Q3 ON Q3.id = M.id AND Q3.Param = 3
LEFT JOIN Session.SubQuery Q4 ON Q4.id = M.id AND Q4.Param = 4;
Решения разработки баз данных