хотите выполнить запрос к каждой базе данных, как рассчитать разницу в производительности в C # и в SQL Server - PullRequest
1 голос
/ 27 января 2012

Я работаю над продуктом SQL Server Monitoring, и у меня есть запрос к базе данных, который будет извлекать данные, относящиеся ко всем подробностям таблицы всех баз данных на SQL-сервере.

Для этого у меня есть два варианта.

  1. Пожарный запрос к базе данных из кода как select name from [master].sys.sysdatabases Сначала получите имя базы данных для всей базы данных, а затем я выполню основной запрос на каждую базу данных. используя "USE <fetched DB name>;"+"mainQuery";

    Пожалуйста, проверьте следующий код для того же.

    public DataTable GetResultsOfAllDB(string query)
    {
        SqlConnection con = new SqlConnection(_ConnectionString);
        string locleQuery = "select name from [master].sys.sysdatabases";
        DataTable dtResult = new DataTable("Result");
        SqlCommand cmdData = new SqlCommand(locleQuery, con);
        cmdData.CommandTimeout = 0;
    
        SqlDataAdapter adapter = new SqlDataAdapter(cmdData);
        DataTable dtDataBases = new DataTable("DataBase");
        adapter.Fill(dtDataBases);
    
        foreach (DataRow drDB in dtDataBases.Rows)
        {
            if (dtResult.Rows.Count >= 15000)
                break;
            locleQuery = " Use [" + Convert.ToString(drDB[0]) + "]; " + query;
            cmdData = new SqlCommand(locleQuery, con);
            adapter = new SqlDataAdapter(cmdData);
            DataTable dtTemp = new DataTable();
            adapter.Fill(dtTemp);
            dtResult.Merge(dtTemp);
        }
        return dtResult;
    }
    
  2. Я буду использовать процедуру хранения sys, т.е. EXEC sp_MSforeachdb, а извлеченные данные будут храниться, сохранять данные в виде данных таблицы. Drop Table искушаем. Проверьте следующий запрос для того же

    Declare @TableDetail table ( field1 varchar(500), field2 int, field3 varchar(500), field4 varchar(500), field5 decimal(18,2), field6 decimal(18,2) ) INSERT @TableDetail EXEC sp_MSforeachdb 'USE [?]; QYERY/COMMAND FOR ALL DATABASE' Select field1,field2 ,field3 ,field4 ,field5,field6 FROM @TableDetail

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

Теперь мой вопрос: какой из двух вариантов является хорошим и почему? или любое другое решение для того же.

Заранее спасибо.

Ответы [ 4 ]

1 голос
/ 27 января 2012

Оба отстой - они оба последовательные.

Используйте первое, избавьтесь от нелепых объектов (DataSet) и используйте ЗАДАЧИ для параллелизации баз данных X одновременно.X определяется попыткой ut, с какой нагрузкой может справиться сервер.

Завершено.

1 голос
/ 27 января 2012

Одно ключевое отличие - блоки второй опции, пока все не будет сделано.Вся работа выполняется на стороне сервера sql.При этом возникает проблема невозможности применения обратной связи к пользователю во время его работы, и это может привести к истечению времени ожидания и не быть устойчивым к сетевым сбоям.Эту опцию можно использовать как чистый SQL-скрипт (например, некоторые администраторы SQL), где первому нужна программа.

В первом примере клиент выполняет итеративные, более детальные задачи, где вы можете предоставить обратную связьпользователь.Вы также можете повторить перед сетевыми сообщениями, не повторяя всю работу.В первом примере вы также можете использовать SqlConnectionBuild вместо конкатенации USE.

Если производительность является проблемой, вы также можете распараллелить первый с некоторой блокировкой вокруг адаптера. Заполните

0 голосов
/ 27 января 2012

Все выглядит хорошо.Я просто хочу добавить Использование операторов для IDisposable объектов

public DataTable GetResultsOfAllDB(string query)
        {
            using (SqlConnection con = new SqlConnection(_ConnectionString))
            {
                string locleQuery = "select name from [master].sys.sysdatabases";
                DataTable dtResult = new DataTable("Result");
                using (SqlCommand cmdData = new SqlCommand(locleQuery, con))
                {
                    cmdData.CommandTimeout = 0;

                    using (SqlDataAdapter adapter = new SqlDataAdapter(cmdData))
                    {

                        using (DataTable dtDataBases = new DataTable("DataBase"))
                        {
                            adapter.Fill(dtDataBases);

                            foreach (DataRow drDB in dtDataBases.Rows)
                            {
                                if (dtResult.Rows.Count >= 15000)
                                    break;
                                locleQuery = " Use [" + Convert.ToString(drDB[0]) + "]; " + query;
                                cmdData = new SqlCommand(locleQuery, con);
                                adapter = new SqlDataAdapter(cmdData);
                                using (DataTable dtTemp = new DataTable())
                                {
                                    adapter.Fill(dtTemp);
                                    dtResult.Merge(dtTemp);
                                }
                            }
                            return dtResult;
                        }
                    }
                }
            }
        }
0 голосов
/ 27 января 2012

Если ваши запросы достаточно просты, вы можете попытаться сгенерировать один скрипт вместо того, чтобы выполнять запросы в каждой БД по одному:

select 'DB1' as DB, Field1, Field2, ...
from [DB1]..[TableOrViewName]
union all
select 'DB2' as DB, Field1, Field2, ...
from [DB2]..[TableOrViewName]
union all
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...