it-swarm.asia

أفضل تصميم قاعدة بيانات وجدول لمليارات صفوف البيانات

أنا أكتب تطبيقًا يحتاج إلى تخزين وتحليل كميات كبيرة من البيانات الكهربائية وبيانات درجة الحرارة.

في الأساس ، أحتاج إلى تخزين كميات كبيرة من قياسات استخدام الكهرباء لكل ساعة للسنوات العديدة الماضية ولسنوات عديدة قادمة لعشرات الآلاف من المواقع ثم تحليل البيانات بطريقة غير معقدة للغاية.

المعلومات التي أحتاج إلى تخزينها (الآن) هي معرف الموقع والطابع الزمني (التاريخ والوقت) ودرجة الحرارة واستخدام الكهرباء.

حول كمية البيانات التي يجب تخزينها ، هذا تقريب ، ولكن شيئًا على هذا المنوال:
20000 موقعًا ، و 720 سجلًا شهريًا (قياسات كل ساعة ، وحوالي 720 ساعة شهريًا) ، و 120 شهرًا (لمدة 10 سنوات) والعديد من السنوات القادمة. تؤدي الحسابات البسيطة إلى النتائج التالية:

20000 موقع × 720 سجل × 120 شهرًا (10 سنوات مضت) = 17800000 سجل.

هذه هي السجلات السابقة ، سيتم استيراد السجلات الجديدة شهريًا ، بحيث يكون هذا تقريبًا 20000 × 720 = 14400000 سجل جديد شهريًا.

سوف ينمو إجمالي المواقع بشكل مطرد أيضًا.

على جميع هذه البيانات ، ستحتاج إلى تنفيذ العمليات التالية:

  1. استرجع البيانات لتاريخ وفترة زمنية معينة: جميع السجلات لمعرف موقع معين بين التاريخين 01.01.2013 و 01.01.2017 وبين 07:00 و 13:00.
  2. عمليات حسابية بسيطة لتاريخ ونطاق زمني معين ، على سبيل المثال MIN ، MAX و AVG درجة الحرارة واستخدام الكهرباء لمعرف موقع معين لمدة 5 سنوات بين 07:00 و 13:00.

ستتم كتابة البيانات شهريًا ، ولكن سيتم قراءتها من قبل مئات المستخدمين (على الأقل) باستمرار ، وبالتالي فإن سرعة القراءة ذات أهمية أكبر.

ليس لدي خبرة في قواعد بيانات NoSQL ولكن من خلال ما جمعته ، فهي أفضل حل لاستخدامه هنا. لقد قرأت على قواعد بيانات NoSQL الأكثر شيوعًا ، ولكن نظرًا لأنها مختلفة تمامًا وتسمح أيضًا ببنية جدول مختلفة تمامًا ، لم أتمكن من تحديد أفضل قاعدة بيانات لاستخدامها.

كانت اختياراتي الرئيسية Cassandra و MongoDB ، ولكن منذ ذلك الحين لدي معرفة محدودة جدًا ولا خبرة حقيقية عندما يتعلق الأمر بالبيانات الكبيرة و NoSQL ، لست متأكدًا تمامًا. قرأت أيضًا أن PostreSQL تتعامل أيضًا هذه الكميات من البيانات بشكل جيد.

أسئلتي هي التالية:

  1. هل يجب علي استخدام قاعدة بيانات NoSQL لمثل هذه الكميات الكبيرة من البيانات. إذا لم يكن بإمكاني التمسك MySQL؟
  2. ما قاعدة البيانات التي يجب استخدامها؟
  3. هل يجب علي الاحتفاظ بالتاريخ والوقت في أعمدة منفصلة ومفهرسة (إن أمكن) لاسترداد البيانات ومعالجتها بسرعة لفترات زمنية وتاريخية معينة ، أم يمكن القيام بذلك عن طريق الاحتفاظ بالطابع الزمني في عمود واحد؟
  4. هل نهج نمذجة بيانات السلاسل الزمنية مناسب هنا ، وإذا لم يكن الأمر كذلك ، هل يمكن أن تعطيني مؤشرات لتصميم جدول جيد؟

شكرا لك.

85
Gecata

هذا هو بالضبط ما أفعله كل يوم ، باستثناء البيانات بدلاً من استخدام بيانات الساعة ، أستخدم بيانات 5 دقائق. أقوم بتنزيل حوالي 200 مليون سجل يوميًا ، لذا فإن المبلغ الذي تتحدث عنه هنا لا يمثل مشكلة. بيانات الخمس دقائق هي حوالي 2 TB في الحجم ولدي بيانات الطقس تعود إلى 50 عامًا على مدار الساعة حسب الموقع. لذا دعني أجب على الأسئلة بناءً على تجربتي:

  1. لا تستخدم NoSQL لهذا الغرض. البيانات منظمة للغاية وتناسب قاعدة بيانات علائقية بشكل مثالي.
  2. أنا شخصيًا أستخدم SQL Server 2016 وليس لدي أي مشاكل في تطبيق العمليات الحسابية عبر حجم البيانات هذا. كان في الأصل على نسخة PostgreSQL عندما بدأت عملي ولم أستطع التعامل مع حجم البيانات كما كان في مثيل AWS صغير.
  3. أود بشدة أن أوصي باستخراج جزء الساعة من التاريخ وتخزينه بشكل منفصل عن التاريخ نفسه. صدقني ، تعلم من أخطائي!
  4. أقوم بتخزين غالبية قائمة البيانات حسب الحكمة (DATE ، TIME ، DATAPOINT_ID ، VALUE) ولكن هذه ليست الطريقة التي سيرغب بها الأشخاص في تفسير البيانات. كن مستعدًا لبعض الاستفسارات الرهيبة مقابل البيانات والكميات الهائلة من التمحور. لا تخف من إنشاء جدول غير طبيعي لمجموعات النتائج التي تكون أكبر من أن تحسب بسرعة.

نصيحة عامة: أقوم بتخزين معظم البيانات بين قاعدتي بيانات ، الأولى هي بيانات السلاسل الزمنية المستقيمة ويتم تطبيعها. قاعدة بياناتي الثانية غير طبيعية وتحتوي على بيانات مجمعة مسبقًا. بالسرعة التي يتمتع بها نظامي ، لست عمياء عن حقيقة أن المستخدمين لا يريدون حتى الانتظار 30 ثانية حتى يتم تحميل التقرير - حتى إذا كنت أفكر شخصيًا في 30 ثانية للتغلب على 2 TB = البيانات سريعة للغاية.

لتوضيح سبب التوصية بتخزين الساعة بشكل منفصل عن التاريخ ، إليك بعض الأسباب التي تجعلني أفعل ذلك بهذه الطريقة:

  1. الطريقة التي يتم بها تقديم البيانات الكهربائية هي نهاية الساعة - لذلك ، 01:00 هو في الواقع متوسط ​​الطاقة الكهربائية للساعة السابقة و 00:00 هو نهاية الساعة 24. (هذا مهم لأنه يجب عليك في الواقع البحث عن تاريخين لتضمين قيمة 24 ساعة - اليوم الذي تبحث عنه بالإضافة إلى العلامة الأولى في اليوم التالي.) ومع ذلك ، يتم تقديم بيانات الطقس في الواقع بطريقة مستقبلية (الفعلية والمتوقعة لـ الساعة القادمة). في تجربتي مع هذه البيانات ، يرغب المستهلكون في تحليل تأثير الطقس على سعر/طلب الطاقة. إذا كنت ستستخدم مقارنة تاريخ مستقيمة ، فستكون في الواقع تقارن متوسط ​​السعر للساعة السابقة مقابل متوسط ​​درجة الحرارة للساعة التالية ، على الرغم من أن الطوابع الزمنية هي نفسها. يسمح لك تخزين الساعة المنفصلة عن التاريخ بتطبيق التحويلات على الوقت بتأثير أقل في الأداء مما قد ترى تطبيق حساب على عمود DATETIME.
  2. أداء. أود أن أقول أن 90 ٪ على الأقل من التقارير التي أقوم بإنشائها هي رسوم بيانية ، وعادة ما يتم رسم السعر مقابل الساعة إما لتاريخ واحد أو لمجموعة من التواريخ. قد تؤدي الحاجة إلى تقسيم الوقت من التاريخ إلى تعطل سرعة الاستعلام المستخدم لإنشاء التقرير اعتمادًا على النطاق الزمني الذي تريد رؤيته. ليس من غير المألوف بالنسبة للمستهلكين أن يرغبوا في رؤية تاريخ واحد ، على أساس سنوي على مدار الثلاثين عامًا الماضية (في الواقع ، بالنسبة للطقس هذا مطلوب لتوليد المعايير العادية لمدة 30 عامًا) - قد يكون هذا بطيئًا. بالطبع يمكنك تحسين الاستعلام الخاص بك وإضافة الفهارس ، وثق بي لدي بعض الفهارس المجنونة التي لا أفضل أن أحصل عليها ولكنها تجعل النظام يعمل بسرعة.
  3. إنتاجية. أكره الاضطرار إلى كتابة نفس الرمز أكثر من مرة. اعتدت على تخزين التاريخ والوقت في نفس العمود ، حتى اضطررت إلى كتابة نفس الاستعلام مرارا وتكرارا لاستخراج جزء الوقت. بعد فترة ، سئمت للتو من القيام بذلك واستخرجته في العمود الخاص به. كلما قل الرمز عليك كتابة فرصة أقل لوجود خطأ فيه. أيضًا ، الحاجة إلى كتابة كود أقل يعني أنه يمكنك الحصول على تقاريرك بشكل أسرع ، لا أحد يريد الانتظار طوال اليوم للحصول على التقارير.
  4. المستخدمين النهائيين. ليس كل المستخدمين النهائيين من المستخدمين المحترفين (أي معرفة كيفية كتابة SQL). إن تخزين البيانات بالفعل بتنسيق يمكن أن يجلبه إلى Excel (أو أداة أخرى مماثلة) بأقل جهد سيجعلك بطلاً في المكتب. إذا لم يتمكن المستخدمون من الوصول إلى البيانات أو معالجتها بسهولة ، فلن يستخدموا نظامك. صدقوني ، لقد صممت النظام المثالي قبل عامين ولم يستخدمه أحد لهذا السبب. لا يقتصر تصميم قاعدة البيانات على الالتزام بمجموعة محددة مسبقًا من القواعد/الإرشادات ، بل يتعلق بجعل النظام قابلاً للاستخدام.

كما قلت أعلاه ، كل هذا يعتمد على تجربتي الشخصية ، ودعوني أخبركم ، لقد مرت سنوات قليلة صعبة والعديد من عمليات إعادة التصميم للوصول إلى ما أنا عليه الآن. لا تفعل ما فعلته ، وتعلم من أخطائي وتأكد من إشراك المستخدمين النهائيين لنظامك (أو المطورين ، مؤلفي التقارير ، إلخ ...) عند اتخاذ قرارات بشأن قاعدة بياناتك.

102
Mr.Brownstone

فهارس PostgreSQL و BRIN

اختبره بنفسك. هذه ليست مشكلة على جهاز كمبيوتر محمول عمره 5 سنوات مع SSD.

EXPLAIN ANALYZE
CREATE TABLE electrothingy
AS
  SELECT
    x::int AS id,
    (x::int % 20000)::int AS locid,  -- fake location ids in the range of 1-20000
    now() AS tsin,                   -- static timestmap
    97.5::numeric(5,2) AS temp,      -- static temp
    x::int AS usage                  -- usage the same as id not sure what we want here.
  FROM generate_series(1,1728000000) -- for 1.7 billion rows
    AS gs(x);

                                                               QUERY PLAN                                                               
----------------------------------------------------------------------------------------------------------------------------------------
 Function Scan on generate_series gs  (cost=0.00..15.00 rows=1000 width=4) (actual time=173119.796..750391.668 rows=1728000000 loops=1)
 Planning time: 0.099 ms
 Execution time: 1343954.446 ms
(3 rows)

لذلك استغرق 22 دقيقة لإنشاء الجدول. إلى حد كبير ، لأن الطاولة بحجم 97 جيجابايت متواضع. بعد ذلك نقوم بإنشاء الفهارس ،

CREATE INDEX ON electrothingy USING brin (tsin);
CREATE INDEX ON electrothingy USING brin (id);    
VACUUM ANALYZE electrothingy;

لقد استغرق إنشاء الفهارس وقتًا طويلاً أيضًا. على الرغم من أنهم BRIN ، إلا أنهم 2-3 ميغابايت ويتم تخزينهم بسهولة في ذاكرة الوصول العشوائي. قراءة 96 غيغابايت ليست فورية ، لكنها ليست مشكلة حقيقية لجهاز الكمبيوتر المحمول الخاص بك في عبء العمل الخاص بك.

الآن نستعلم عنها.

explain analyze
SELECT max(temp)
FROM electrothingy
WHERE id BETWEEN 1000000 AND 1001000;
                                                                 QUERY PLAN                                                                  
---------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=5245.22..5245.23 rows=1 width=7) (actual time=42.317..42.317 rows=1 loops=1)
   ->  Bitmap Heap Scan on electrothingy  (cost=1282.17..5242.73 rows=993 width=7) (actual time=40.619..42.158 rows=1001 loops=1)
         Recheck Cond: ((id >= 1000000) AND (id <= 1001000))
         Rows Removed by Index Recheck: 16407
         Heap Blocks: lossy=128
         ->  Bitmap Index Scan on electrothingy_id_idx  (cost=0.00..1281.93 rows=993 width=0) (actual time=39.769..39.769 rows=1280 loops=1)
               Index Cond: ((id >= 1000000) AND (id <= 1001000))
 Planning time: 0.238 ms
 Execution time: 42.373 ms
(9 rows)

تحديث مع الطوابع الزمنية

هنا ننشئ جدولًا يحتوي على طوابع زمنية مختلفة من أجل تلبية طلب الفهرسة والبحث في عمود الطابع الزمني ، يستغرق الإنشاء وقتًا أطول قليلاً لأن to_timestamp(int) أبطأ بكثير من now() (التي تم تخزينه مؤقتًا للمعاملة)

EXPLAIN ANALYZE
CREATE TABLE electrothingy
AS
  SELECT
    x::int AS id,
    (x::int % 20000)::int AS locid,
    -- here we use to_timestamp rather than now(), we
    -- this calculates seconds since Epoch using the gs(x) as the offset
    to_timestamp(x::int) AS tsin,
    97.5::numeric(5,2) AS temp,
    x::int AS usage
  FROM generate_series(1,1728000000)
    AS gs(x);

                                                               QUERY PLAN                                                                
-----------------------------------------------------------------------------------------------------------------------------------------
 Function Scan on generate_series gs  (cost=0.00..17.50 rows=1000 width=4) (actual time=176163.107..5891430.759 rows=1728000000 loops=1)
 Planning time: 0.607 ms
 Execution time: 7147449.908 ms
(3 rows)

الآن يمكننا تشغيل استعلام على قيمة الطابع الزمني بدلاً من ذلك ،،

explain analyze
SELECT count(*), min(temp), max(temp)
FROM electrothingy WHERE tsin BETWEEN '1974-01-01' AND '1974-01-02';
                                                                        QUERY PLAN                                                                         
-----------------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=296073.83..296073.84 rows=1 width=7) (actual time=83.243..83.243 rows=1 loops=1)
   ->  Bitmap Heap Scan on electrothingy  (cost=2460.86..295490.76 rows=77743 width=7) (actual time=41.466..59.442 rows=86401 loops=1)
         Recheck Cond: ((tsin >= '1974-01-01 00:00:00-06'::timestamp with time zone) AND (tsin <= '1974-01-02 00:00:00-06'::timestamp with time zone))
         Rows Removed by Index Recheck: 18047
         Heap Blocks: lossy=768
         ->  Bitmap Index Scan on electrothingy_tsin_idx  (cost=0.00..2441.43 rows=77743 width=0) (actual time=40.217..40.217 rows=7680 loops=1)
               Index Cond: ((tsin >= '1974-01-01 00:00:00-06'::timestamp with time zone) AND (tsin <= '1974-01-02 00:00:00-06'::timestamp with time zone))
 Planning time: 0.140 ms
 Execution time: 83.321 ms
(9 rows)

نتيجة:

 count |  min  |  max  
-------+-------+-------
 86401 | 97.50 | 97.50
(1 row)

لذا في 83.321 مللي ثانية يمكننا تجميع 86.401 تسجيلًا في جدول يحتوي على 1.7 مليار صف. يجب أن يكون ذلك معقولاً.

نهاية الساعة

يعد حساب نهاية الساعة أمرًا سهلاً للغاية أيضًا ، واقطع الطوابع الزمنية لأسفل ثم ببساطة أضف ساعة.

SELECT date_trunc('hour', tsin) + '1 hour' AS tsin,
  count(*),
  min(temp),
  max(temp)
FROM electrothingy
WHERE tsin >= '1974-01-01'
  AND tsin < '1974-01-02'
GROUP BY date_trunc('hour', tsin)
ORDER BY 1;
          tsin          | count |  min  |  max  
------------------------+-------+-------+-------
 1974-01-01 01:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 02:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 03:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 04:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 05:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 06:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 07:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 08:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 09:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 10:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 11:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 12:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 13:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 14:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 15:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 16:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 17:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 18:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 19:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 20:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 21:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 22:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-01 23:00:00-06 |  3600 | 97.50 | 97.50
 1974-01-02 00:00:00-06 |  3600 | 97.50 | 97.50
(24 rows)

Time: 116.695 ms

من المهم ملاحظة أنه لا يستخدم فهرسًا على التجميع ، على الرغم من أنه يمكن ذلك. إذا كان هذا هو استعلامك المعتاد ، فمن المحتمل أنك تريد BRIN في date_trunc('hour', tsin) وهنا تكمن مشكلة صغيرة في أن date_trunc غير قابل للتغيير ، لذا عليك أولاً لفه لجعله كذلك.

التقسيم

نقطة أخرى مهمة للمعلومات عن PostgreSQL هي أن PG 10 يجلب تقسيم DDL . لذلك ، على سبيل المثال ، يمكنك بسهولة إنشاء أقسام لكل عام. تقسيم قاعدة بياناتك المتواضعة إلى ثانوية صغيرة. عند القيام بذلك ، يجب أن تكون قادرًا على استخدام والحفاظ على فهارس btree بدلاً من BRIN التي ستكون أسرع.

CREATE TABLE electrothingy_y2016 PARTITION OF electrothingy
    FOR VALUES FROM ('2016-01-01') TO ('2017-01-01');

أو أيا كان.

63
Evan Carroll

يدهشني أنه لم يذكر أحد هنا قياس الأداء - أي حتى @ EvanCarroll جاء مع مساهمته الممتازة!

إذا كنت مكانك ، كنت سأقضي بعض الوقت (ونعم ، أعلم أنها سلعة ثمينة!) لإعداد الأنظمة ، وتشغيل ما تعتقد أنه سيكون (احصل على مدخلات المستخدم النهائي هنا!) ، على سبيل المثال ، 10 استفساراتك الأكثر شيوعًا.

أفكاري الخاصة:

يمكن أن تعمل حلول NoSQL بشكل جيد جدًا في حالات الاستخدام الخاصة ولكنها غالبًا ما تكون غير مرنة بالنسبة لاستعلامات الأقران. للحصول على لقطة مسلية على NoSQL بواسطة Brian Aker - كبير مهندسي MySQL السابق ، انظر هنا !

أتفق مع @ Mr.Brownstone في أن بياناتك مناسبة بشكل واضح لحل علائقي (وهذا الرأي تم تأكيده بواسطة Evan Carroll )!

إذا كنت سألتزم بأي نفقات ، فسيكون ذلك لتقنيتي على القرص! سأقوم بإنفاق أي أموال كنت في حوزتي على NAS أو SAN أو ربما بعض أقراص SSD للاحتفاظ ببيانات مجمعة نادرًا مكتوبة!

أولاً أود أن أنظر إلى ما هو متوفر لدي الآن . قم بإجراء بعض الاختبارات وأظهر النتائج لصناع القرار. لديك بالفعل وكيل على شكل عمل EC ! ولكن ، اختبارًا سريعًا أو اثنين معًا على الأجهزة الخاصة بك سيكون أكثر إقناعًا!

ثم فكر في إنفاق المال! إذا كنت تنفق الأموال ، فابحث عن الأجهزة أولاً بدلاً من البرامج. AFAIK ، يمكنك الاستعانة بتكنولوجيا القرص لفترة تجريبية ، أو الأفضل من ذلك ، عرض مجموعة من بروفات المفاهيم على السحابة.

أول منفذ شخصي خاص بي لمشروع مثل هذا سيكون PostgreSQL. هذا لا يعني أنني سأستبعد حل الملكية ، ولكن قوانين الفيزياء والأقراص هي نفسها للجميع! "Yae cannae beet the قوانين الفيزياء جيم" :-)

14
Vérace

إذا لم تكن قد فعلت ذلك بالفعل ، فقم بإلقاء نظرة على سلسلة DBMS ، لأنها محسنة لتخزين البيانات والاستعلام عنها حيث يكون التركيز الأساسي هو نوع التاريخ/الوقت. عادةً ما يتم استخدام قواعد بيانات السلاسل الزمنية لتسجيل البيانات في نطاقات الدقيقة/الثانية/الفرعية الثانية ، لذلك لست متأكدًا مما إذا كانت لا تزال مناسبة لزيادات كل ساعة. ومع ذلك ، يبدو أن هذا النوع من DBMS يستحق النظر فيه. يبدو أن InfluxDB حاليًا هي قاعدة بيانات السلاسل الزمنية الأكثر استخدامًا والأكثر استخدامًا.

6
FloorDivision

من الواضح أن هذه ليست مشكلة NoSQL ، لكنني أقترح أنه في حين أن حل RDBMS سيعمل ، أعتقد أن نهج OLAP سيكون مناسبًا بشكل أفضل نظرًا لنطاقات البيانات المحدودة جدًا المعنية ، أود بشدة اقترح التحقيق في استخدام قاعدة بيانات تستند إلى عمود بدلاً من صف واحد. فكر في الأمر بهذه الطريقة ، فقد يكون لديك 1.7 مليار قطعة من البيانات ، ولكنك لا تزال بحاجة إلى 5 بت فقط لفهرسة كل قيمة محتملة للساعة أو اليوم من الشهر.

لدي خبرة في مجال مشكلة مماثلة حيث يتم استخدام Sybase IQ (الآن SAP IQ) لتخزين ما يصل إلى 300 مليون عدادات في الساعة من بيانات إدارة أداء معدات الاتصالات ، لكني أشك في وجود ميزانية لهذا النوع من الحلول. في ساحة مفتوحة المصدر ، يعد MariaDB ColumnStore مرشحًا واعدًا للغاية ، لكني أوصي أيضًا بالتحقيق في MonetDB.

نظرًا لأن أداء طلب البحث هو محرك رئيسي لك ، فكر في كيفية صياغة الاستعلامات. هذا هو المكان OLAP و RDBMS تظهر اختلافاتهما الكبرى: - مع OLAP تطبيع لأداء الاستعلام ، وليس لتقليل التكرار ، أو تقليل التخزين أو حتى لفرض الاتساق لذا بالإضافة إلى الطابع الزمني الأصلي (هل تذكرت التقاط المنطقة الزمنية التي آملها؟) يحتوي على حقل منفصل للطابع الزمني UTC ، وآخر للتاريخ والوقت ، ومع ذلك أكثر للسنة والشهر واليوم والساعة ، دقيقة وإزاحة UTC. إذا كانت لديك معلومات إضافية حول المواقع ، فلا تتردد في الاحتفاظ بذلك في جدول موقع منفصل يمكن البحث عنه عند الطلب ولا تتردد في الاحتفاظ بمفتاح هذا الجدول في سجلك الرئيسي ولكن احتفظ باسم الموقع بالكامل في الجدول الرئيسي الخاص بك أيضًا ، بعد كل شيء ، لا تزال جميع المواقع المحتملة تستغرق 10 بتات فقط للفهرسة وكل مرجع لا يتعين عليك اتباعه للحصول على البيانات التي يتم الإبلاغ عنها هو توفير الوقت في الاستعلام الخاص بك.

كاقتراح أخير ، استخدم جداول منفصلة للبيانات المجمعة الشائعة واستخدم المهام المجمعة لملئها ، وبهذه الطريقة لن تضطر إلى تكرار التمرين لكل تقرير يستخدم قيمة مجمعة ويجعل الاستعلامات التي تقارن الحالية بالبيانات السابقة أو التاريخية تاريخي إلى تاريخي أسهل بكثير وأسرع بكثير.

4
Paul Smith