إنه يوم باي! لنحسب باي باستخدام SQL
عيد Pi سعيد! خطر لنا أن يكون من الممتع حساب pi باستخدام استعلامات SQL في ClickHouse. إليك ما توصّلنا إليه حتى الآن…
- يستخدم هذا المثال دالة الجدول
numbers_mt في ClickHouse لإرجاع مليار صف، ولا يستغرق سوى 40 ملّي ثانية لحساب النتيجة:
SELECT 4 * sum(if(number % 2, -1, 1) / ((number * 2) + 1)) AS pi
FROM numbers_mt(1000000000.)
┌────────────────pi─┐
│ 3.141592652589797 │
└───────────────────┘
1 row in set. Elapsed: 0.432 sec. Processed 1.00 billion rows, 8.00 GB (2.32 billion rows/s., 18.53 GB/s.)
- يعالج المثال التالي أيضًا مليار رقم، ولكن ليس بهذه السرعة:
SELECT 3 + (4 * sum(if((number % 2) = 0, if((number % 4) = 0, -1 / ((number * (number + 1)) * (number + 2)), 1 / ((number * (number + 1)) * (number + 2))), 0))) AS pi
FROM numbers_mt(2, 10000000000)
┌─────────────────pi─┐
│ 3.1415926525808087 │
└────────────────────┘
1 row in set. Elapsed: 9.825 sec. Processed 10.00 billion rows, 80.00 GB (1.02 billion rows/s., 8.14 GB/s.)
- هذا بلا شك خيارنا المفضل في ClickHouse (وهو الأدق!):
SELECT pi()
┌──────────────pi()─┐
│ 3.141592653589793 │
└───────────────────┘
1 row in set. Elapsed: 0.008 sec.
- يبدو أن أحدهم كان يعرف حساب المثلثات جيدًا في هذه المسألة:
SELECT 2 * asin(1) AS pi
┌────────────────pi─┐
│ 3.141592653589793 │
└───────────────────┘
1 row in set. Elapsed: 0.005 sec.
- إليك واجهة برمجة تطبيقات مفيدة تتيح لك تحديد عدد الأرقام التي تريدها:
SELECT *
FROM url('https://api.pi.delivery/v1/pi?start=0&numberOfDigits=100', 'JSONEachRow')
┌───────────────content─┐
│ 3.1415926535897933e99 │
└───────────────────────┘
1 row in set. Elapsed: 0.556 sec.
- هذا ذكي - إذ يستخدم دوال المسافة في ClickHouse:
WITH random_points AS
(
SELECT (rand64(1) / pow(2, 64), rand64(2) / pow(2, 64)) AS point
FROM numbers(1000000000)
)
SELECT (4 * countIf(L2Norm(point) < 1)) / count() AS pi
FROM random_points
┌──────────pi─┐
│ 3.141627208 │
└─────────────┘
1 row in set. Elapsed: 4.742 sec. Processed 1.00 billion rows, 8.00 GB (210.88 million rows/s., 1.69 GB/s.)
- إذا كنت فيزيائيًا، فسيعجبك هذا:
SELECT 22 / 7
┌─────divide(22, 7)─┐
│ 3.142857142857143 │
└───────────────────┘
- طريقة غير مباشرة أخرى (اقترحها Alexey Milovidov) دقيقة حتى 7 منازل عشرية - وهي سريعة:
WITH
10 AS length,
(number / 1000000000.) * length AS x
SELECT pow((2 * length) * avg(exp(-(x * x))), 2) AS pi
FROM numbers_mt(1000000000.)
┌─────────────────pi─┐
│ 3.1415926890388595 │
└────────────────────┘
1 row in set. Elapsed: 1.245 sec. Processed 1.00 billion rows, 8.00 GB (803.25 million rows/s., 6.43 GB/s.)
إذا كان لديك المزيد، فسنكون سعداء بمساهمتك بها. شكرًا!