問題の概要:
Web サービスを使用して複数のデバイスから集中型データベースに収集するデータを記述するデータベース テーブルがあります。
結果を格納するテーブルは、パフォーマンスのために意図的に非正規化されています。複数のインデックスによるクエリとグループ化が高速化されています。 データ アクセスには Entity Framework と Linq を使用しています。
階層的なグループ化とプロジェクションを使用して、 Linq クエリを適切に設計する必要があります。
デバイス データベース モデリングの概要:
現在、私は2種類のデバイスを持っています
1. RFID デバイス
最初のテーブルは、データを収集するタグを記述する RfidTag であり、1 つの RfidTag = 1 つのセンサーです。たとえば、1 つのタグで温度に関するデータを取得できます。
2 番目の表は RfidReader で、添付されたタグからすべてのデータを収集して送信する読み取りモジュールについて説明しています。1 つの RfidReader に添付される RfidTags の数に制限はありません。ただし、読み取り期間中は、1 つの RfidReader に 1 つの RfidTag を付けることができます。
CREATE TABLE [dbo].[RfidTag]
(
Id INT IDENTITY(1,1),
CreatedDateTime DATETIME NOT NULL DEFAULT GETDATE(),
ModifiedDateTime DATETIME,
--
ReaderId INT NULL, -- Reference to reader
SensorTypeId INT NOT NULL, -- Reference to sensor type
SensorParameters NVARCHAR(50) NULL, -- Sensor parameters
Hex NVARCHAR(50) NOT NULL, -- Hex tag identifier stored as string
Name NVARCHAR(50) NOT NULL, -- Tag name
[Description] NVARCHAR(200) NULL, -- Tag description
--
)
CREATE TABLE [dbo].[RfidReader]
(
Id INT IDENTITY(1,1),
CreatedDateTime DATETIME NOT NULL DEFAULT GETDATE(),
ModifiedDateTime DATETIME,
--
Name NVARCHAR(20), -- Tag name
[Description] NVARCHAR(200), -- Tag description
SerialNumber NVARCHAR(12), -- Unique device serial name
--
)
各 RfidReaderは、特定の構造について説明されている特定の測定ゾーンに取り付けることができます。
CREATE TABLE [dbo].[RfidReaderPlacement]
(
Id INT IDENTITY(1,1),
CreatedDateTime DATETIME NOT NULL DEFAULT GETDATE(),
--
ReaderId INT NOT NULL, -- Reference to Reader.
MeasurementZoneId INT NOT NULL, -- Reference to Measurement Zone.
StartDate DATETIME NOT NULL, -- Start date of reading.
StopDate DATETIME, -- End date of reading.
--
)
RfidTag によって収集された単一のデータは、非正規化されたテーブルに保存されます。このテーブルには何百万ものレコードが格納されており、負荷が非常に高くなっています。このテーブルから、LINQ クエリを使用してデータを収集します。
CREATE TABLE [dbo].[RfidReading]
(
Id INT IDENTITY(1,1),
CreatedDateTime DATETIME NOT NULL DEFAULT GETDATE(),
ModifiedDateTime DATETIME,
--
ReaderPlacementId INT NOT NULL, -- Reference to Rfid Reader Placement
ConstructionId INT NOT NULL, -- Reference to Construction
MeasurementZoneId INT NOT NULL, -- Reference to Measurement Zone
ReaderId INT NOT NULL, -- Reference to Rfid Reader
TagId INT NOT NULL, -- Reference to Rfid Tag
SensorTypeId INT NOT NULL, -- Reference to Sensor Type
ReadingDate DATETIME NOT NULL, -- Reading date
Value FLOAT NOT NULL -- Measured value
--
)
2. ZigBee デバイス
最初の表は、データを収集する単一のプローブを記述する ZigBeeNodeProbe です。1つの単一の ZigBeeNodeProbe = 1 つの単一のセンサーです。たとえば、1 つのプローブで温度に関するデータを取得できます。
2 番目のテーブルは、接続されたプローブを含む単一のデバイスを説明する ZigBeeNode です。1 つの単一 ZigBeeNode = 3 ZigBeeNodeProbesです。
3 番目の表は、接続されたノードからすべてのデータを収集して送信する読み取りモジュールを説明する ZigBeeReader です。1 つの ZigBeeReader に接続されている (ZigBeeNodeProbe が接続されている) ZigBeeNode の数に制限はありません。ただし、読み取り期間中は、1 つの ZigBeeNode を 1 つの ZigBeeReader に接続できます。
CREATE TABLE [dbo].[ZigBeeNodeProbe]
(
Id INT IDENTITY(1,1),
CreatedDateTime DATETIME NOT NULL DEFAULT GETDATE(),
--
NodeId INT NULL, -- Reference to node
SensorTypeId INT NOT NULL, -- Reference to sensor type
SensorParameters NVARCHAR(50) NULL, -- Sensor parameters
SocketNumber INT NOT NULL, -- Socket number used in parent ZigBeeNode
Name NVARCHAR(50) NOT NULL, -- Node name
[Description] NVARCHAR(200) NULL, -- Node description
--
)
CREATE TABLE [dbo].[ZigBeeNode]
(
Id INT IDENTITY(1,1),
CreatedDateTime DATETIME NOT NULL DEFAULT GETDATE(),
ModifiedDateTime DATETIME,
--
ReaderId INT NULL, -- Reference to reader
NetworkAddress NVARCHAR(50) NOT NULL,-- Node address in ZigBee network
Name NVARCHAR(50) NOT NULL, -- Given name
[Description] NVARCHAR(200) NULL, -- Tag description
SocketCount INT NOT NULL DEFAULT 0, -- Count of available sockets to plug in probe
NodeFrequency INT NULL, -- Node frequency
)
CREATE TABLE [dbo].[ZigBeeReader]
(
Id INT IDENTITY(1,1),
CreatedDateTime DATETIME NOT NULL DEFAULT GETDATE(),
ModifiedDateTime DATETIME,
--
Name NVARCHAR(20), -- Tag name
[Description] NVARCHAR(200), -- Tag description
SerialNumber NVARCHAR(12), -- Unique device serial name
--
)
各 ZigBeeReaderは、特定の構造について説明されている特定の測定ゾーンに取り付けることができます。
CREATE TABLE [dbo].[ZigBeeReaderPlacement]
(
Id INT IDENTITY(1,1),
CreatedDateTime DATETIME NOT NULL DEFAULT GETDATE(),
--
ReaderId INT NOT NULL, -- Reference to Reader.
MeasurementZoneId INT NOT NULL, -- Reference to Measurement Zone.
StartDate DATETIME NOT NULL, -- Start date of reading.
StopDate DATETIME, -- End date of reading.
--
)
ZigBeeNodeProbe によって収集された単一のデータは、非正規化されたテーブルに保存されます。このテーブルには何百万ものレコードが格納されており、負荷が非常に高くなっています。このテーブルから、LINQ クエリを使用してデータを収集します。
CREATE TABLE [dbo].[ZigBeeReading]
(
Id INT IDENTITY(1,1),
CreatedDateTime DATETIME NOT NULL DEFAULT GETDATE(),
ModifiedDateTime DATETIME,
--
ReaderPlacementId INT NOT NULL, -- Reference to ZigBee Reader Placement
ConstructionId INT NOT NULL, -- Reference to Construction
MeasurementZoneId INT NOT NULL, -- Reference to Measurement Zone
ReaderId INT NOT NULL, -- Reference to ZigBee Reader
NodeId INT NOT NULL, -- Reference to ZigBee Node
ProbeId INT NOT NULL, -- Reference to ZigBee Node Probe
SensorTypeId INT NOT NULL, -- Reference to Sensor Type
ReadingDate DATETIME NOT NULL,-- Reading date
Value FLOAT NOT NULL -- Measured value
--
)
クエリ、グループ化、射影の問題:
上記のように、前述の 2 種類のデバイスによって収集されたデータを含む 2 つの分散テーブルがあります。はい、RfidTag は ZigBeeNodeProbe とほぼ同じビジネス モデリングであると想定できます。
RfidReader
-- RFidTag
-- RFidTag
...
ZigBeeReader
-- ZigBeeNode
---- ZigBeeNodeProbe
---- ZigBeeNodeProbe
---- ZigBeeNodeProbe
-- ZigBeeNode
---- ZigBeeNodeProbe
---- ZigBeeNodeProbe
---- ZigBeeNodeProbe
...
次に、これらの両方のテーブルにクエリを実行し、異なるテーブルの値を同じビュー モデルに射影し、データをフィルター処理するための特定のグループを追加する必要があります。
一般的なシナリオ:
特定の測定ゾーンの平均温度を表すチャートを作成したいのですが、特定の測定ゾーンには複数のリーダー (Rfid と ZigBee の両方) が接続されている可能性があるため、一連のデータを提供する必要があることに注意してください。
有効にしている必要があるHightStock http://www.highcharts.com/products/highstockチャートを使用しています。
- 1か月、3か月、6か月などのZoom
- 開始日、終了日
- 機能のエクスポート
- シリーズの有効化と無効化の凡例
チャートの例:
問題:
階層データの LINQ グループ化と射影クエリを作成する方法は? RfidReading テーブルと ZigBeeReading テーブルの両方に共通のビュー モデルを提供する必要があります。
私の最初の試みは次のようなものでした:
public class ReadingReaderDataModel
{
public string SeriesName { get; set; }
public ReadingPeriod ReadingPeriod { get; set; }
public IEnumerable<ReadingNodeDataModel> ReadingNodeDataModels { get; set; }
public ReadingReaderDataModel()
{
ReadingNodeDataModels = new List<ReadingNodeDataModel>();
}
}
public class ReadingNodeDataModel
{
public string NodeName { get; set; }
public IEnumerable<double> DataValues { get; set; }
public ReadingNodeDataModel()
{
DataValues = new LinkedList<double>();
}
}
public enum ReadingPeriod
{
OneMonth, ThreeMonths, SixMonths, YearToDay, OneYear, All
}
public enum ReaderType
{
Rfid, ZigBee
}
後で、ASP.NET MVC コントローラーの LINQ プロジェクションを設計する必要があります。ここでは、OneMonth、ThreeMonths、SixMonths、YearToDay、OneYear、All でグループ化された期間の平均値を含む必要がある適切なクエリを作成する方法がわかりません。
この高度な LINQ クエリの設計を手伝ってくれる人はいますか?
編集
大規模なデータセットの「推奨事項」を私に指摘しないでください...
これはパフォーマンスの問題ではありません。
この質問は、複雑な LINQ クエリに関するものです。私は適切なLINQコードを探していますが、「その車は速いので、その車を使用する必要があります」などの回答ではありません...コードの回答をお願いします...シナリオを理解しようとせず、コードを提供しない場合は、しないでください参加...
この質問の主題のように高度なLINQの質問であるため、LINQの解決策を見つけるために特別に報奨金を追加しました。