0

В течение последних нескольких дней я читал электронную книгу о структурах данных, и, честно говоря, многие вещи уже исчезли из моей головы. Просто просмотрите их и повторите попытку. Я проходил через хэш-таблицы и снова знаком с ним. Поэтому я знаю и слышу, SQL Server использует хеш-таблицы внутри, а многие потоки stackoverflow.com и forums.asp.net задают вопрос о создании хеш-таблиц в SQL Server, поскольку он хранит временные данные. Итак, позвольте мне привести пример, который я использовал в хранимой процедуре, используя временную таблицу: (Избегайте его, и это слишком долго просто для примера.)Структура данных таблицы хэшей в SQL Server

первый:

CREATE PROCEDURE [dbo].[Orders] 
    @OrderLine int 
AS 
BEGIN 
    DECLARE @t1 TABLE(Date1 date, 
         OrderID VARCHAR(MAX), 
         EmployeeName VARCHAR(MAX), 
         DeliveryDate date, 
         StoreName VARCHAR(MAX), 
         DeliveryAddress VARCHAR(MAX), 
         ItemName VARCHAR(MAX), 
         Quantity FLOAT) 

    INSERT INTO @t1(Date1, OrderID, EmployeeName, DeliveryDate, StoreName, DeliveryAddress, ItemName, Quantity) 
     (SELECT DISTINCT 
      CONVERT(VARCHAR(11), DemandOrder.POCreationDate, 6) AS DemandOrderDate, 
      DemandOrder.OrderID, EmployeeDetails.EmployeeName, 
      CONVERT(DATE, DemandOrder.DeliveryDate) AS ExpectedDeliveryDate, 
      StoreDetails.StoreName, 
      DemandOrder.DeliveryAddress, Item.ItemName, 
      DemandOrderLine.Quantity 
     FROM 
      DemandOrder 
     INNER JOIN 
      DemandOrderLine ON DemandOrder.OrderID = DemandOrderLine.OrderID 
     INNER JOIN 
      Item on DemandOrderLine.ItemID=Item.ItemID 
     INNER JOIN 
      EmployeeDetails ON EmployeeDetails.EmployeeID = DemandOrder.EmployeeID 
     INNER JOIN 
      StoreDetails ON DemandOrderLine.StoreID = StoreDetails.StoreID 
     WHERE 
      DemandOrderLine.OrderLine = @OrderLine) 

    DECLARE @t2 TABLE(Approvedby VARCHAR(MAX)) 

    INSERT INTO @t2(Approvedby) 
     (SELECT EmployeeDetails.EmployeeName 
     FROM EmployeeDetails 
     INNER JOIN DemandOrderLine ON DemandOrderLine.ApprovedBy = EmployeeDetails.EmployeeID) 

    SELECT DISTINCT 
     CONVERT(VARCHAR(11), Date1, 6) AS Date, 
     OrderID, EmployeeName, 
     CONVERT(VARCHAR(11), DeliveryDate, 6) AS ExpectedDeliveryDate, 
     StoreName, Approvedby, DeliveryAddress, 
     ItemName, Quantity 
    FROM 
     @t1 
    CROSS JOIN 
     @t2 
END 

Еще один, из примера, который хранится в хранимой процедуре, хеш-таблицы не могут использоваться. Так вот это:

второй:

CREATE PROCEDURE TempTable AS ---- It's actually not possible in SP 

CREATE table #Color 
(
    Color varchar(10) PRIMARY key 
) 

INSERT INTO #color 
    SELECT 'Red' 
    UNION 
    SELECT 'White' 
    UNION 
    SELECT 'green' 
    UNION 
    SELECT 'Yellow' 
    UNION 
    SELECT 'blue' 

DROP TABLE #color 

CREATE table #Color 
(
    Color varchar(10) PRIMARY key 
) 

INSERT INTO #color 
    SELECT 'Red' 
    UNION 
    SELECT 'White' 
    UNION 
    SELECT 'green' 
    UNION 
    SELECT 'Yellow' 
    UNION 
    SELECT 'blue' 

DROP TABLE #color 
GO 

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

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

+0

Я думаю, что у вас может быть некоторая путаница между хеш-таблицами и таблицами с префиксом символа '#' [(hash)] (https://en.m.wikipedia.org/wiki/Number_sign)? Последние не имеют ничего общего с хэш-таблицей компьютерных наук. Это просто требование именования локальных временных таблиц. –

ответ

3

Это слишком долго для комментария.

Хэш-алгоритмы важны для любой мощной базы данных. Они используются для операций агрегации и объединения. Присоединения на основе хэшей были там с версии 7.0, которая действительно старая (благодаря Мартину Смиту). Вы можете узнать больше о них в documentation.

SQL Server 2014 представил индексы на основе хэшей для оптимизированных по памяти таблиц (см. here). Это явное использование хеш-таблиц. В целом, однако, индексы на основе дерева являются более мощными, поскольку они могут быть использованы в большем количестве ситуаций:

  • Для поиска в диапазоне (в том числе like).
  • Для неполных ключевых совпадений.
  • Для order by.

Хэш-индекс может использоваться только для точного совпадения равенства (и group by).

+0

ОК и оцените ваш ответ @ Gordon Linoff. Первый ** SP **, который я включил, может быть примером хеш-таблиц? Или я ошибаюсь. –

+0

SQL Server не получал хэш-соединения до тех пор, пока SQL Server 7.0 https://msdn.microsoft.com/en-us/library/aa226170(v=sql.70).aspx –

1

Пожалуйста, обратите внимание также следующие примечания как расширенный комментарий, а не как отдельный ответ:

[1] SQL Server есть присоединиться (INNER HASH JOIN) и подсказки запроса (OPTION (HASH JOIN), OPTION(HAS GROUP')) в целях обеспечения соблюдения таких физических объединений или группировки ,

[2] Внутри SQL Server использует хеш-таблицу как идентификаторы блокировки. См. Недокументированную функцию %% lockres %% (ссылка http://www.sqlskills.com/blogs/paul/investigating-locking-and-deadlocking-with-lockres/).

USE tempdb 
GO 

CREATE TABLE dbo.Documents (
    ID   INT IDENTITY(1,1) PRIMARY KEY, 
    DocDate  DATE NOT NULL, 
    Content  VARCHAR(8000) NOT NULL 
); 

CREATE INDEX IX_Documents_DocDate 
ON dbo.Documents (DocDate) 
GO 

INSERT dbo.Documents (DocDate, Content) 
VALUES 
('2016-01-01', REPLICATE(CONVERT(VARCHAR(MAX), 'A'), 4000)), 
('2016-02-02', REPLICATE(CONVERT(VARCHAR(MAX), 'B'), 5000)), 
('2016-03-04', REPLICATE(CONVERT(VARCHAR(MAX), 'C'), 6000)); 
GO 

SELECT ID, DocDate, %%lockres%% AS record_lock_hash 
FROM dbo.Documents WITH(INDEX=1) -- Clustered index 
GO 
/* 
ID   DocDate record_lock_hash 
----------- ---------- -------------------------------- 
1   2016-01-01 (8194443284a0) 
2   2016-02-02 (61a06abd401c) 
3   2016-03-04 (98ec012aa510) 
*/ 
GO 

SELECT ID, DocDate, %%lockres%% AS record_lock_hash 
FROM dbo.Documents WITH(INDEX=IX_Documents_DocDate) -- Non-Clustered index 
GO 
/* 
ID   DocDate record_lock_hash 
----------- ---------- -------------------------------- 
1   2016-01-01 (417e1de8c3fb) 
2   2016-02-02 (6aede25aab61) 
3   2016-03-04 (e701c6578164) 
*/ 
GO 

[3] В качестве разработчика баз данных, я использовал "хэш-таблицы" (вычисляемый столбец определен с использованием хеш-функции) для индекса большой текст (или капли), таким образом:

ALTER TABLE dbo.Documents 
ADD ContentHash AS CHECKSUM(HASHBYTES('sha256', Content)) /*PERSISTED*/ -- Computed column 
GO 

SET ANSI_NULLS, QUOTED_IDENTIFIER ON 
GO 
SET ANSI_WARNINGS, ANSI_PADDING, ARITHABORT, CONCAT_NULL_YIELDS_NULL ON 
SET NUMERIC_ROUNDABORT OFF 
GO 

CREATE INDEX IX_Documents_ContentHash 
ON dbo.Documents (ContentHash) 
--INCLUDE (Content) 
GO 

DECLARE @ParamContent VARCHAR(8000) = REPLICATE(CONVERT(VARCHAR(MAX), 'B'), 5000) 

DECLARE @ParamHash INT = CHECKSUM(HASHBYTES('sha256', @ParamContent)) 
SELECT d.ID, d.Content 
FROM dbo.Documents d WITH(FORCESEEK) 
WHERE d.ContentHash = @ParamHash -- Index Seek Predicate (Fast/optimized if there is an index on ContentHash computed column) 
AND  d.Content = @ParamContent -- [Simple/non-indexed] Predicate (Slow) 
GO 

enter image description here

Примечание: пожалуйста, играть с вниманием, когда indexing computed columns (см. Требования к SET).

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