table_open_cache=1024000
НЕТ! Это таблиц , а не байтов . Измените его на 2000
.
key_buffer_size=2147483648
Если вы используете InnoDB, а не MyISAM:
key_buffer_size = 50M
innodb_buffer_pool_size is fine at 96G (for 128GB of RAM)
Это почти бесполезно, измените на 5
:
long_query_time=100
И ... [ 1116]
# Thread Specific Values
sort_buffer_size=2147483648
read_buffer_size=2147483648
read_rnd_buffer_size=1073741824
join_buffer_size=1073741824
bulk_insert_buffer_size=4294967296
tmp_table_size=17179869184
max_heap_table_size=8589934592
Прочитайте этот комментарий! Каждое соединение может распределять эти размеры! Вам не хватит оперативной памяти. Поменяться местами или произойдет сбой! Даже если у вас много оперативной памяти, эти цифры чрезмерны.
innodb_flush_method = unbuffered
В руководстве говорится:
unbuffered: ... используется для внутреннего тестирования производительности и в настоящее время не поддерживается. Используйте на свой страх и риск.
blockquote>innodb_random_read_ahead = 1
Из руководства:
Поскольку эта функция может улучшить производительность в некоторых случаях и снизить производительность в других, прежде чем полагаться на этот параметр, проведите тестирование как с, так и без настройка включена.
blockquote>Итог: отменить все ваши изменения конфигурации , кроме buffer_pool.
С новым MS SQL 2005 Вы могли использовать WITH
ключевое слово
Проверьте этот вопрос и особенно этот ответ.
С Oracle Вы могли использовать CONNECT BY
ключевое слово для генерации иерархических запросов (синтаксис).
AFAIK с MySQL необходимо будет использовать рекурсию.
Кроме того, Вы могли всегда создавать таблицу кэша для своего родителя записей-> дочерние отношения
Как общий ответ, возможно сделать некоторый довольно сложный материал в SQL Server, которому обычно нужна рекурсия, просто при помощи итеративного алгоритма. Мне удалось выполнить, синтаксический анализатор XHTML Проводит SQL, который работал удивительно хорошо. Код prettifier, который я записал, был сделан в хранимой процедуре. Это не изящно, это скорее похоже на буйвола наблюдения, делающего Балет. но это работает.
Вы используете SQL 2005?
Раз так можно использовать Общие Выражения Таблицы для этого. Что-то вдоль этих строк:
;
with CTE (Some, Columns, ItemId, ParentId) as
(
select Some, Columns, ItemId, ParentId
from myTable
where ItemId = @itemID
union all
select a.Some, a.Columns, a.ItemId, a.ParentId
from myTable as a
inner join CTE as b on a.ParentId = b.ItemId
where a.ItemId <> b.ItemId
)
select * from CTE
Проблема, с которой Вы столкнетесь с рекурсией и производительностью, состоит в том, сколько раз она должна будет рекурсивно вызвать для возврата результатов. Каждый рекурсивный вызов является другим отдельным вызовом, к которому нужно будет присоединиться в общие результаты.
В SQL 2k5 можно использовать общее выражение таблицы для обработки этой рекурсии:
WITH Managers AS
(
--initialization
SELECT EmployeeID, LastName, ReportsTo
FROM Employees
WHERE ReportsTo IS NULL
UNION ALL
--recursive execution
SELECT e.employeeID,e.LastName, e.ReportsTo
FROM Employees e INNER JOIN Managers m
ON e.ReportsTo = m.employeeID
)
SELECT * FROM Managers
или другое решение состоит в том, чтобы сгладить иерархию в другую таблицу
Employee_Managers
ManagerId (PK, FK к Списку сотрудников)
EmployeeId (PK, FK к Списку сотрудников)
Все родительские дочерние отношения были бы сохранены в этой таблице, поэтому если бы менеджер 1 справляется, менеджер 2 управляет сотрудником 3, таблица была бы похожа:
ManagerId EmployeeId
1 2
1 3
2 1
Это позволяет иерархии быть легко запрошенной:
select * from employee_managers em
inner join employee e on e.employeeid = em.employeeid and em.managerid = 42
Который возвратил бы всех сотрудников, которые имеют менеджера 42. Позитивный аспект будет большей производительностью, но оборотная сторона будет поддержанием иерархии
Возможно, еще некоторая деталь в порядке.
Если у Вас будут отношения основной детали, как Вы описываете, то разве, простое СОЕДИНЕНИЕ не получит то, в чем Вы нуждаетесь?
Как в:
SELECT
SOME_FIELDS
FROM
MASTER_TABLE MT
,CHILD_TABLE CT
WHERE CT.PARENT_ID = MT.ITEM_ID
Вам не нужна рекурсия вообще.... Отметьте, я изменил столбцы на ItemID и ItemParentID для простоты ввода...
DECLARE @intLevel INT SET @intLevel = 1INSERT INTO TempTable(ItemID, ItemParentID, Level) SELECT ItemID, ItemParentID, @intLevel WHERE ItemParentID IS NULL
WHILE @intLevel < @TargetLevel BEGIN SET @intLevel = @intLevel + 1 INSERT INTO TempTable(ItemID, ItemParentID, Level) SELECt ItemID, ItemParentID, @intLevel WHERE ItemParentID IN (SELECT ItemID FROM TempTable WHERE Level = @intLevel-1) -- If no rows are inserted then there are no children IF @@ROWCOUNT = 0 BREAK END
SELECt ItemID FROM TempTable WHERE Level = @TargetLevel
Вам не должна быть нужна рекурсия для детей - Вы только смотрите на уровень непосредственно ниже (т.е. select * from T where ParentId = @parent
) - Вам только нужна рекурсия для всех потомков.
В SQL2005 можно получить потомков с:
with AllDescendants (ItemId, ItemText) as (
select t.ItemId, t.ItemText
from [TableName] t
where t.ItemId = @ancestorId
union
select sub.ItemId, sub.ItemText
from [TableName] sub
inner join [TableName] tree
on tree.ItemId = sub.ParentItemId
)
У Joe Celko есть книга (<-связываются с Amazon), конкретно на древовидных структурах в базах данных SQL. В то время как Вам была бы нужна рекурсия для Вашей модели и определенно будет потенциал для проблем производительности там, существуют альтернативные способы смоделировать древовидную структуру в зависимости от того, что включает Ваша определенная проблема, который мог избежать рекурсии и дать лучшую производительность.