2014-02-20 2 views
0

Извините за мой плохой английский.Ускорить поиск записей в очень большом sql-столе

Пожалуйста, предположим, что мы хотим сохранить все коммерческие действия (продать & купить) за все дни, и каждый день имеет

100 или больше действий. Через 3 года у нас есть таблица с более чем 100 000 строк. Теперь мы хотим получить

отчет о действиях, выполненных за 2 года назад между 5/20 по 5/25.

SELECT * 
    FROM actions 
WHERE Date BETWEEN 2012/5/20 AND 2012/5/25 

Проблема в том, что для этого необходимо прочитать все 100 000 строк.

Во-первых, я решил разделить данные за каждый месяц в разделенных таблицах. Но я не знаю, как

обрабатывать это с сущностью. Есть ли у вас предложение? Благодарю.

+0

Что вы спрашиваете об индексировании, разбиении на разделы и т. Д. Предложите вам прочитать книгу или использовать онлайн-материалы. – Punter015

ответ

2

Не предполагайте, что ваш запрос будет вести себя плохо, если в ваших таблицах будет X количество строк. Вы должны проверить это!

Очень легко создать несколько миллионов строк тестовых данных для каждой из ваших таблиц (должно быть сделано в среде разработки или тестирования). Затем вы можете проверить каждый из своих запросов и посмотреть, как именно они будут медленными.

Этот фрагмент создаст стол и вставляет в него 1 000 000 рядов. Попробуйте и попробуйте запустить несколько разных запросов.

CREATE TABLE [dbo].[Orders](
    [OrderId] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED, 
    [CustomerId] [int] NOT NULL, 
    [ArticleId] [int] NOT NULL, 
    [TotalAmount] [decimal](19, 6) NULL, 
    [OrderDate] DATETIME NOT NULL DEFAULT(GETDATE()) 
); 

WITH 
      C0(c) AS (SELECT 1 UNION ALL SELECT 1), 
      C1(c) AS (SELECT 1 FROM C0 AS A CROSS JOIN C0 AS B), 
      C2(c) AS (SELECT 1 FROM C1 AS A CROSS JOIN C1 AS B), 
      C3(c) AS (SELECT 1 FROM C2 AS A CROSS JOIN C2 AS B), 
      C4(c) AS (SELECT 1 FROM C3 AS A CROSS JOIN C3 AS B), 
      C5(c) AS (SELECT 1 FROM C4 AS A CROSS JOIN C4 AS B), 
      C6(c) AS (SELECT 1 FROM C5 AS A CROSS JOIN C5 AS B), 

     numbers(n) AS(
         SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) 
       FROM C6) 

INSERT dbo.Orders 
     (CustomerId , 
      ArticleId , 
      TotalAmount, 
      OrderDate 
     ) 
SELECT TOP 1000000 
     N % 150 + 1, 
     N % 100 + 1, 
     N % 500 + 20, 
     DATEADD(MINUTE, (N - 1), '2014-01-01') 
FROM numbers; 

Таблица будет содержать 1 000 000 заказов, сделано 150 различных Клиенты, в течение 100 различных статей, на сумму от 20 до 520 каждого. Каждый заказ помещается с одной минутой между собой, начиная с 2014-01-01 00:00:00.

Используя эти данные, следующий запрос все еще выполняется в рамках одной секунды на моей рабочей станции:

SELECT * FROM dbo.Orders WHERE orderDate BETWEEN '2014-05-01' AND '2014-08-01' 

данных имеют тенденцию быть намного меньше на диске, чем вы думаете. Эта таблица с ОДНОМ МИЛЛИОННЫМИ рядами в ней по-прежнему занимает около 70 МБ пространства.

EXEC sys.sp_spaceused @objname = N'Orders' 
--name  rows  reserved data  index_size unused 
--Orders 1000000  70432 KB 37560 KB 32072 KB 800 KB 

Сколько времени требуется, чтобы прочитать эту большую часть МБ с диска?2-3 секунды, в худшем случае на рабочем столе.

Добавление индексов: Прокомментировать другие ответы.

Я добавил индекс в столбец даты, но оптимизатор запросов по-прежнему считал, что лучше сканировать всю таблицу. Вероятно, это связано с тем, что более дорогостоящим образом выполнять поиск для всех этих заказов в диапазоне дат, чем читать все последовательно с диска. В зависимости от данных в таблице эти индексы могут использоваться или не использоваться. Вот почему вы должны генерировать тестовые данные, соответствующие ожидаемой нагрузке, только тогда вы можете настроить свои запросы и создать «правильные» индексы.

Для этой конкретной таблицы и, возможно, в вопросе, я бы предложил поместить индекс CLUSTERED в столбец даты вместо первичного ключа.

3

Проблема в том, что для этого необходимо прочитать все 100 000 строк.

A: ДАЖЕ ЕСЛИ - это было бы тривиально, если вы не запустили его на старый мобильный телефон. Я регулярно собираю 100 миллионов строк из таблицы из 10 миллиардов строк.

B: Узнайте, что такое индекс, тогда не все строки должны быть прочитаны.

+0

Можете ли вы, пожалуйста, пояснить раздел B? –

+2

Да. Получите книгу. Например, «Sql для чайников». Прочтите. Вам не хватает абсолютных принципов sql. – TomTom

1

Прежде всего, 100 000 строк не будут проблемой для SQL Server, если у вас есть правильные индексы, это будет прекрасно даже после 30 лет.

Если вы все еще хотите, чтобы разбить его, я бы не сделать это вручную, что будет слишком много беспорядка, просто используйте таблицу разбиения, которая обрабатывается сам SQL Server (http://technet.microsoft.com/en-us/library/ms190787.aspx для получения дополнительной информации)

+0

Спасибо захорак. Я видел, что в моих друзьях проект прочитывал 500 000 строк в 10 минут! Считаете ли вы, что на этот раз плохо, и у них была неизвестная проблема? –

+0

зависит от типа строк и данных, которые он читает, одна строка с 4 числовыми столбцами не совпадает с строкой с 8 Кбайт данных - если вы хотите прочитать все данные там, не используя индекс, чем вы имея дело с 4 ГБ данных (8K * 500 000). Но, как уже упоминалось в другом ответе, использование индекса поможет – peter

Смежные вопросы